---
title: "Get Objective Outcomes"
method: POST
path: "/api/analytics/objective-outcomes"
tags: ["analytics"]
---

# Get Objective Outcomes

`POST /api/analytics/objective-outcomes`

## Request

- Base URL: `https://api.vruum.ai`
- URL: `https://api.vruum.ai/api/analytics/objective-outcomes`
- Auth: `HTTPBearer` (a scheme the document does not define)

Compare objectives on real outcomes — contacted, replied, verified meetings.

A legacy outreach campaign is an objective now — pass its objective id,
not the campaign id.

Answers "which of these objectives actually worked" for up to 100
objectives in one call, over an explicit UTC window. Every objective you
ask for comes back, including ones with no usable data — those carry
`availability: "unavailable"` rather than being dropped or reported as
zero, so an objective never looks like a failure when it is really just
unmeasured.

**Use `get_performance_metrics` instead** for funnel and time-series views
of the whole account; this tool is for ranking specific objectives against
each other on a like-for-like cohort.

Reading the response:

- **`outcome_cutoff`** is the "as of" moment. A reply or meeting counts
  only if it happened by then, so an objective that started last week is
  not punished for outcomes that have not had time to land. Keep it
  identical across objectives you intend to compare.
- **`meetings`** counts people with a verified meeting: it started by
  `outcome_cutoff` and was not cancelled, internal, or marked as a
  no-show. **`booked_meetings`** counts the other people with a live
  booking that has not started: progress, never a result.
- **`coverage_complete: false`** means attribution for that objective is
  still incomplete. Report the numbers, but do not rank on them — that is
  the difference between "performed badly" and "we cannot tell yet".
- **`data_watermark`** is how far message and meeting ingestion has caught
  up. Outcomes after the watermark are not in these numbers yet.
- **`computed_at`** stamps the calculation, which is worth quoting when
  the same window is re-run later and moves.

Window rules the server enforces: all three timestamps must carry a UTC
offset, `start_at < end_at <= outcome_cutoff`, and `outcome_cutoff` cannot
be in the future. `objective_ids` must be unique.

## Request body

- ObjectiveOutcomesQuery
  - `objective_ids` string[], required
  - `start_at` string, date-time, required
  - `end_at` string, date-time, required
  - `outcome_cutoff` string, date-time, required

## Response `200`

Successful Response

- ObjectiveOutcomesResponse: Canonical REST/MCP batch response (VRU-878 PR B) — the objective-keyed twin of the retired ``CampaignOutcomesResponse``: same shape, ``items`` keyed by ``objective_id``/``objective_name`` instead of ``campaign_id``/``campaign_name``.
  - `computed_at` string, date-time, required
  - `outcome_cutoff` string, date-time, required
  - `coverage_complete` boolean, required
  - `coverage_warning` string, nullable
  - `items` ObjectiveOutcomeItem[], required
    - `objective_id` string, uuid, required
    - `objective_name` string, nullable
    - `availability` 'available' | 'unavailable', required
    - `unavailable_reason` 'objective_not_found', nullable
    - `contacted` integer, required
    - `replied` integer, required
    - `meetings` integer, required: Cohort people with a verified meeting: live (not cancelled, not a no-show, not internal, not a logged interaction) and its start time inside [start_at, outcome_cutoff), so it has passed.
    - `booked_meetings` integer, required: Other cohort people with a live booking whose start has not passed by outcome_cutoff: progress, never a result.
    - `won` integer, required
    - `reply_rate` number, required
    - `meeting_rate` number, required
    - `attribution_quality` 'exact' | 'reconstructed' | 'inferred', required
    - `exact_count` integer, required
    - `reconstructed_count` integer, required
    - `inferred_count` integer, required
    - `coverage_complete` boolean, required
    - `data_watermark` ObjectiveOutcomeWatermark, required
      - `latest_contact` string, date-time, nullable
      - `latest_contact_observed` string, date-time, nullable
      - `pending_sends` integer
      - `won_basis` string, nullable
    - `reply` ConversionReading, required: ``Rate.as_dict()`` typed for the generated client.
      - `metric` string, required
      - `value` number, nullable
      - `percent` number, nullable
      - `numerator` integer, nullable
      - `denominator` integer, required
      - `metric_definition_version` string, required
      - `sample` 'ok' | 'insufficient_sample', required
      - `floor` integer, required
      - `channel` string, nullable
      - `unmeasurable` string, nullable
    - `meeting` ConversionReading, required: ``Rate.as_dict()`` typed for the generated client.
      - `metric` string, required
      - `value` number, nullable
      - `percent` number, nullable
      - `numerator` integer, nullable
      - `denominator` integer, required
      - `metric_definition_version` string, required
      - `sample` 'ok' | 'insufficient_sample', required
      - `floor` integer, required
      - `channel` string, nullable
      - `unmeasurable` string, nullable

## Other responses

- `422`: Validation Error
- `502`: Objective outcome RPC response violated its contract
- `503`: Objective outcome data dependency is unavailable

---

[API](https://skmtc.dev/vruum/apis/vruum-public-api.md) · [All operations](https://skmtc.dev/vruum/apis/vruum-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/vruum/apis/vruum-public-api/revisions/b8ada111c30a?raw)
