---
title: Report Outcome Event
api: POST /track/outcomes/report
description: "Record an outcome event for the learning loop — accepted, rejected, completed, or observed at 7/30/90 days."
---

> **For AI agents:** the complete documentation index is at [llms.txt](https://docs.boringmarketing.com/llms.txt). Append `.md` to any page URL for its markdown version.

Records a single outcome event for a recommendation. This is the write side of the learning loop — the read side is `GET /brands/{brand_id}/outcomes`.

Events are persisted as artifacts and feed the leverage scoring calibration over time. Supported lifecycle: `accepted → completed → observed_7d → observed_30d → observed_90d`, plus `rejected` for queue items you declined.

<Note>
This endpoint is feature-flagged. Returns **503** if `OE_OUTCOME_LINKAGE_ENABLED` is not set in the environment.
</Note>

## Request body

<ParamField body="brand_id" type="string" required>
  The brand UUID.
</ParamField>

<ParamField body="event_type" type="string" required>
  One of: `accepted`, `rejected`, `completed`, `observed_7d`, `observed_30d`, `observed_90d`.
</ParamField>

<ParamField body="recommendation_id" type="string">
  The opportunity UUID that this event relates to. Strongly recommended for any event other than generic brand-level logs.
</ParamField>

<ParamField body="brief_id" type="string">
  The brief UUID, if this event relates to a generated brief.
</ParamField>

<ParamField body="rejection_reason" type="string">
  Required when `event_type` is `rejected`. Free-text reason.
</ParamField>

<ParamField body="metrics" type="object">
  Arbitrary metrics captured with the event. Useful on `observed_*` events to store rank/citation deltas from `GET /track/brands/{id}/changes`. As of PR #112, the `metrics` object is persisted into the outcome event's `delta` field — no longer silently dropped — so anything you store here will round-trip on read.
</ParamField>

<ParamField body="notes" type="string">
  Free-text notes (e.g. published URL, author, internal reference).
</ParamField>

## Response

```json
{
  "outcome_event_id": "outcome-uuid",
  "artifact_id": "artifact-uuid",
  "status": "recorded"
}
```

## Example — publish event

```bash
curl -X POST \
  -H "X-API-Key: $BM_API_KEY" \
  -H "Content-Type: application/json" \
  https://api.boringmarketing.com/track/outcomes/report \
  -d '{
    "brand_id": "'$BRAND_ID'",
    "recommendation_id": "opp-uuid",
    "brief_id": "brief-uuid",
    "event_type": "completed",
    "notes": "Published at https://yourdomain.com/article"
  }'
```

## Example — 7-day observation with deltas

```bash
curl -X POST \
  -H "X-API-Key: $BM_API_KEY" \
  -H "Content-Type: application/json" \
  https://api.boringmarketing.com/track/outcomes/report \
  -d '{
    "brand_id": "'$BRAND_ID'",
    "recommendation_id": "opp-uuid",
    "event_type": "observed_7d",
    "metrics": {
      "rank_delta": 8,
      "citation_delta": 2,
      "from_snapshot": "snap-1",
      "to_snapshot": "snap-2"
    }
  }'
```

<Tip>
For consistency, pair every `completed` event with an immediate `POST /track/brands/{id}/snapshot` so later diffs have a clean baseline. See the [Tracking Outcomes guide](https://docs.boringmarketing.com/guides/tracking-outcomes) for the full pattern.
</Tip>
