---
title: "Add or replace a success metric"
method: POST
path: "/api/v1/initiatives/{id}/success-metrics"
tags: ["Initiatives"]
---

# Add or replace a success metric

`POST /api/v1/initiatives/{id}/success-metrics`

## Request

- Base URL: `https://www.useboom.ai`
- URL: `https://www.useboom.ai/api/v1/initiatives/{id}/success-metrics`
- Auth: HTTP bearer

Configure what counts as success for an initiative: a customer-data event, a record on a custom object, or a value extracted from the conversation, measured within 48 hours of the first message. Omit `rootId` to add a metric; pass an existing metric's `rootId` to replace it with a new version. This is not a patch — send the metric's complete configuration, because omitted fields are cleared. Successes are recalculated on every read, so replacing a metric also changes what the dashboard reports for past conversations. Use success_metrics_catalog to find the event, object type or variable to point at.

## Path parameters

- `id` string, required: The initiative id.

## Request body

- object
  - `rootId` string: Omit to add a new metric. Pass an existing metric's `rootId` to replace it with a new version.
  - `name` string, required: The metric label, shown in the dashboard picker.
  - `signalType` 'CDP_EVENT' | 'CUSTOM_OBJECT' | 'EXTRACTED_VARIABLE': What counts as success: a customer-data event, a record on a custom object, or a value extracted from the conversation. Default CDP_EVENT.
  - `aggregation` 'COUNT' | 'SUM' | 'AVERAGE' | 'MAX': How matched values roll up. COUNT needs no value field; SUM, AVERAGE and MAX each require one. Default COUNT.
  - `roiEnabled` boolean: Whether this metric's dashboard shows ROI — attributed sales over what the journey's messages cost, at Boom's fixed average rates. Only meaningful when the metric sums a money value, so it is forced off for COUNT. Default false.
  - `eventName` string, nullable: Required when signalType is CDP_EVENT: the event name that marks success.
  - `valueProperty` string, nullable: The numeric event property to aggregate. Required when signalType is CDP_EVENT and aggregation is not COUNT.
  - `valueSource` 'EVENT_PROPERTY' | 'RELATED_OBJECT': Whether the aggregated value lives on the event itself or on a custom object the event points at. Default EVENT_PROPERTY.
  - `valueObjectTypeId` string, nullable: Required when valueSource is RELATED_OBJECT: the custom-object type to read the value from.
  - `valueRefProperty` string, nullable: Required when valueSource is RELATED_OBJECT: the event property holding the object's external id.
  - `variableId` string, nullable: Required when signalType is EXTRACTED_VARIABLE: the extracted variable that defines success.
  - `objectTypeId` string, nullable: Required when signalType is CUSTOM_OBJECT: the custom-object type a qualifying record belongs to.
  - `objectAttributeFilter` object, nullable: Optional equality filter on the object's attributes, e.g. {"status":"SUCCEEDED"}.
  - `objectTimeAttribute` string, nullable: Required when signalType is CUSTOM_OBJECT: the attribute holding the business timestamp to measure against.
  - `objectValueAttribute` string, nullable: The numeric object attribute to aggregate. Required when signalType is CUSTOM_OBJECT and aggregation is not COUNT.
  - `linkagePath` object[], nullable: How the object is linked to a person. Omit or send an empty array when it is linked directly.
    - `kind` 'PERSON_OBJECT' | 'OBJECT_OBJECT', required
    - `role` string, required
    - `direction` 'PARENT_TO_CHILD' | 'CHILD_TO_PARENT'
    - `objectTypeId` string, required

## Response `201`

Success

- object
  - `rootId` string, required: Stable id for this metric across versions. Pass it back to edit the metric.
  - `version` integer, required: Version number; every edit creates a new one.
  - `status` 'ACTIVE' | 'SUPERSEDED', required
  - `name` string, required
  - `signalType` 'CDP_EVENT' | 'CUSTOM_OBJECT' | 'EXTRACTED_VARIABLE', required
  - `aggregation` 'COUNT' | 'SUM' | 'AVERAGE' | 'MAX', required
  - `roiEnabled` boolean, required
  - `eventName` string, nullable, required
  - `valueProperty` string, nullable, required
  - `valueSource` 'EVENT_PROPERTY' | 'RELATED_OBJECT', required
  - `valueObjectTypeId` string, nullable, required
  - `valueRefProperty` string, nullable, required
  - `variableId` string, nullable, required
  - `objectTypeId` string, nullable, required
  - `objectAttributeFilter` object, nullable, required
  - `objectTimeAttribute` string, nullable, required
  - `objectValueAttribute` string, nullable, required
  - `linkagePath` object[], nullable, required
    - `kind` 'PERSON_OBJECT' | 'OBJECT_OBJECT', required
    - `role` string, required
    - `direction` 'PARENT_TO_CHILD' | 'CHILD_TO_PARENT'
    - `objectTypeId` string, required
  - `windowHours` integer, required: Hours after the first outbound message in which a signal still counts. Fixed at 48.
  - `createdAt` string, required: ISO 8601 timestamp of this version.

## Other responses

- `400`: Validation failed or the request cannot proceed.
- `401`: Missing, malformed, or revoked API key.
- `404`: The resource does not exist in this organization.
- `409`: Conflicts with the current state (duplicates, wrong lifecycle state).
- `422`: The request is well-formed but semantically invalid.
- `429`: Rate limit exceeded — retry after `Retry-After`.
- `500`: Internal server error.
- `503`: Transient error — retry with a narrower request.

## Changes

- **2026-11-03** `7c7a773b12ce`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/useboom/apis/boom-api/changes/api/v1/initiatives/:id/success-metrics/post.md)

---

[API](https://skmtc.dev/useboom/apis/boom-api.md) - [All operations](https://skmtc.dev/useboom/apis/boom-api/llms.txt) - [OpenAPI document](https://skmtc.dev/useboom/apis/boom-api/revisions/d596d92ed092?raw)
