> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reconifyhq.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Reconify's API reference is read-only for customer data. Do not invent endpoints or authentication behavior beyond the OpenAPI contract.
> The public OpenAPI document contains only the documented external /v2 contract.

# Trace a flow across services

> Choose correlation and causation IDs across services and investigate with them.

When one business transaction moves through several services, each service reports its own
flow under its own `reference`. One shared `correlation_id` ties those references together,
so an investigation starts from the whole transaction instead of one leg of it.
[Correlation IDs](/concepts/correlation-ids) covers what the field changes and what it
leaves alone.

## Correlation or causation

| Field            | Answers                                     | Shape                                    |
| ---------------- | ------------------------------------------- | ---------------------------------------- |
| `reference`      | Which business flow is this?                | Shared by every event in one operation   |
| `correlation_id` | What broader context did this come from?    | Shared by many events, across references |
| `causation_id`   | Which single earlier event led to this one? | Names exactly one prior event            |

Correlation is shared; causation points. If you find yourself putting the same
value on ten events, that is a correlation ID.

## Choose the value

The right value identifies the business transaction, not a single request.

For `causation_id`, send the event `id` that led directly to this event. It may
be an event your service sent or an upstream event, and Reconify accepts the
value even when it has not seen that event. It is not a `reference`, a shared
`correlation_id`, or the event that merely happened just before this one in time:
sequence is not causation.

| Good candidate                      | Why it works                                    |
| ----------------------------------- | ----------------------------------------------- |
| Checkout or session ID              | Created once, read by every downstream service. |
| Saga or workflow instance ID        | Already spans the services you want to link.    |
| Order ID, when payouts reference it | Survives past the payment leg.                  |

Three kinds of value do not survive the hop:

* A per-request HTTP trace ID. It changes on every call, so two services rarely
  report the same one.
* A provider transaction ID. It exists only after the provider responds, so the
  earliest events cannot carry it.
* A value only one service can compute.

<Warning>
  Do not derive the value from customer data. It is stored as evidence and shown
  during investigation. Use an internal, opaque identifier.
</Warning>

## Add it to your events

Your services already pass some context around. The correlation ID rides along with it,
and every event picks it up on the way out:

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const correlated = events.map((event) => ({
    ...event,
    ...(checkoutId ? { correlation_id: checkoutId } : {}),
  }));

  await client.ingestion.ingestMonitoringEvents({ body: { events: correlated } });
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  correlated = [
      MonitoringEvent(**event, correlation_id=checkout_id)
      if checkout_id
      else MonitoringEvent(**event)
      for event in events
  ]

  client.ingestion.ingest_monitoring_events(
      MonitoringBatchRequest(events=correlated)
  )
  ```
</CodeGroup>

A missing value means the field comes off the event entirely. Sending `""` or `null` is
rejected, while sending nothing is valid and leaves reference-based monitoring untouched.

<Note>
  A rollout works one service at a time. Events without the field keep working, and the
  services that do send it start linking as soon as two of them share a value.
</Note>

## Example: a marketplace checkout

One checkout, `chk_7Q2M0S`, produces two monitored flows in two services.

The payments service reports the buyer payment under `pay_9f2`:

```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --fail-with-body -sS -X POST "https://api.reconifyhq.com/v2/events" \
  -H "Authorization: Bearer $RECONIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id":"evt_01J3Y0M8VJQ5W1R3E4J4K7N8W5","flow":"payment_to_order","type":"payment.succeeded","occurred_at":"2026-01-01T12:00:00Z","amount":"150.00","currency":"USD","reference":"pay_9f2","correlation_id":"chk_7Q2M0S","entity_id":"ord_5512"}'
```

The order service completes the same flow, reusing the same `reference` because
it is the same operation:

```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --fail-with-body -sS -X POST "https://api.reconifyhq.com/v2/events" \
  -H "Authorization: Bearer $RECONIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id":"evt_01J3Y0M8VJQ5W1R3E4J4K7N8X6","flow":"payment_to_order","type":"order.fulfilled","occurred_at":"2026-01-01T12:03:00Z","amount":"150.00","currency":"USD","reference":"pay_9f2","correlation_id":"chk_7Q2M0S","entity_id":"ord_5512"}'
```

The payouts service reports the seller payout. Different flow, different
`reference`, same `correlation_id`:

```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --fail-with-body -sS -X POST "https://api.reconifyhq.com/v2/events" \
  -H "Authorization: Bearer $RECONIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id":"evt_01J3Y0M8VJQ5W1R3E4J4K7N8Y7","flow":"wallet_to_payout","type":"payout.initiated","occurred_at":"2026-01-01T12:05:00Z","amount":"142.50","currency":"USD","reference":"pyt_31a","correlation_id":"chk_7Q2M0S","entity_id":"wlt_88"}'
```

Reconify now holds two operations, evaluated independently:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
Operation pay_9f2   payment_to_order    payment.succeeded, order.fulfilled
Operation pyt_31a   wallet_to_payout    payout.initiated, ...
                    └─ linked by correlation chk_7Q2M0S; caused by payment.succeeded
```

If the payout never completes, the finding stays on `pyt_31a`, where its
deadline lives. The correlation ID is what lets you get from that finding back
to the checkout that produced the related evidence.

## Investigate with it

The dashboard search accepts the correlation value, and it also accepts any `reference`
whose events carry one.

| You search   | Direct results                       | Related activity                              |
| ------------ | ------------------------------------ | --------------------------------------------- |
| `chk_7Q2M0S` | Events carrying that correlation ID. | Both operations and their issues.             |
| `pay_9f2`    | That operation and its events.       | The payout leg, reached through `chk_7Q2M0S`. |

Related results are labeled, so the evidence you asked for stays separate from
the evidence Reconify matched.

When related activity looks wrong, [Troubleshooting](/guides/troubleshooting#related-activity-is-missing-or-wrong)
covers the two causes: a value only one service sends, and a value reused across
transactions.

## Next

<Columns cols={2}>
  <Card title="Correlation IDs" icon="link" href="/concepts/correlation-ids">
    The model, the value rules, and what stays unchanged.
  </Card>

  <Card title="Troubleshoot" icon="life-buoy" href="/guides/troubleshooting">
    Work through rejected items, retries, and stalled events.
  </Card>
</Columns>
