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

> ## Agent Instructions
> Prices are US dollars per contract that pays $1: 0.46 means 46 cents. Spread is the Yes ask plus the No ask minus $1. Liquidity grades are deep, tradeable and thin; lists hide thin markets unless include_thin=true. Relations are proven from contract terms, never inferred from wording; a lead marked informational is never executable. Every figure carries a graph_run; read /agents/reading-order first, then /concepts/relations and /concepts/liquidity.

# Proof trail

> Why two markets are related: the contract versions, the steps, and the runs that found and confirmed it.

Every relation Routeur states can be opened up. `GET /v1/relations/{left_venue}/{left_id}/{right_venue}/{right_id}` returns the proof behind the relation in the latest graph: both contract versions with the structured terms the proof read, the steps in the order the graph applies them, the evidence recorded when the relation was first found, and the runs that found and last confirmed it. The steps are rebuilt from the stored contract versions with the same code that builds the graph, so an explanation can never say more than the graph does.

## Reading a trail

```bash theme={null}
curl "https://api.routeur.app/v1/relations/kalshi/KXSCOTTISHPREMSPREAD-26SEP19HIBABE-ABE3/kalshi/KXSCOTTISHPREMSPREAD-26SEP19HIBABE-ABE2" \
  -H "X-API-Key: $ROUTEUR_API_KEY"
```

Either market may be given first; the trail is stated from the **left** market's side.

| Field                                | Meaning                                                                                                                                |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `relation`                           | From the left market's side: `implies`, `implied_by`, `equivalent`, `contradicts` or `overlaps`. See [Relations](/concepts/relations). |
| `graph_relation`                     | The same relation in the graph's own vocabulary: `subset`, `superset`, `equivalent`, `contradicts` or `overlaps`.                      |
| `direction`                          | `left_implies_right`, `right_implies_left`, `both_ways`, `mutually_exclusive` or `neither`.                                            |
| `cross_venue`                        | Whether the two markets are on different venues.                                                                                       |
| `left`, `right`                      | The two contract versions (below).                                                                                                     |
| `steps`                              | The proof, in order (below).                                                                                                           |
| `evidence`                           | What the graph recorded when it found the relation, as sentences.                                                                      |
| `reproduced`                         | Whether rebuilding the graph from the stored contract versions today yields the stored relation.                                       |
| `found_by`                           | The graph run that first stated this relation between these contract versions: `id`, `graph_version`, `started_at`, `finished_at`.     |
| `confirmed_by`                       | The latest run, which still lists both contract versions and this relation.                                                            |
| `first_seen_at`, `last_confirmed_at` | When `found_by` and `confirmed_by` finished.                                                                                           |

### Each contract

| Field                                                                      | Meaning                                                                                                                                      |
| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `venue`, `id`, `event_id`, `event_title`, `title`, `yes_label`, `no_label` | The market as listed.                                                                                                                        |
| `rules_hash`                                                               | The contract version the proof holds for. A rules change is a new version, and the proof is re-run against it. See [Rules](/concepts/rules). |
| `rules`                                                                    | The rule text of that version.                                                                                                               |
| `strike`                                                                   | The structured strike: `type`, `floor`, `cap`, custom terms and the hash of the rules template with its bounds masked.                       |
| `event_mutually_exclusive`                                                 | Whether the source event says at most one of its markets resolves Yes.                                                                       |
| `variable`                                                                 | The quantity the contract's Yes set is a range of, as the proof read it.                                                                     |
| `interval`                                                                 | The Yes set on that variable in interval notation over exact decimals: `(2.5, ∞)` is "more than 2.5"; `[3, 7)` includes 3 and excludes 7.    |
| `settlement`                                                               | `payout_currency` (`USD` or `USDC`); `scope`, what settlement reads, such as which periods of a game count; `closes_at`; `game_starts_at`.   |
| `first_seen_at`                                                            | When this contract version was first recorded.                                                                                               |

## Step kinds

Each step has a `step` kind, what each side contributed as `left` and `right`, what it established as `result`, and where it helps a `detail` in plain words. `relation` appears only on the conclusion.

| `step`               | Establishes                                                                                                                                                                                                                                   | `result` values                                                                                                                                             |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `usable`             | Whether a contract can enter any proof at all. Only present when one cannot.                                                                                                                                                                  | `incomplete_identity_or_payout`, `source_invalid`                                                                                                           |
| `same_event`         | Both markets belong to the same source event.                                                                                                                                                                                                 | `same`                                                                                                                                                      |
| `same_variable`      | Within a venue: both strikes are on one variable, meaning the same event, the same custom strike terms and the same rules template with its bounds masked. Cross-venue, for economic pairs: both contracts observe one variable the same way. | `same`, or a reason they do not                                                                                                                             |
| `intervals`          | The two Yes sets compared with exact arithmetic.                                                                                                                                                                                              | `subset`, `superset`, `equivalent`, `contradicts`, `overlaps`, or `ambiguous` when the answer depends on endpoint inclusivity the rules state only in prose |
| `mutually_exclusive` | The source event asserts at most one of its markets resolves Yes.                                                                                                                                                                             | `contradicts`                                                                                                                                               |
| `game_quantity`      | Cross-venue sports: what each contract measures (a total, or one team's margin) in one game.                                                                                                                                                  | `same_kind`, `different_kind`, or a reason the quantity could not be read                                                                                   |
| `same_game`          | Both contracts settle on one game: league, date, teams, start time and settlement scope match.                                                                                                                                                | `same`, `not_matched`                                                                                                                                       |
| `orient_margin`      | Margins are stated on one team. When the contracts name opposite teams, one interval is negated so both read on the same team.                                                                                                                | `same_subject`, `negated`                                                                                                                                   |
| `econ_quantity`      | Cross-venue economics: what each contract measures (a data series for a period) and the bucket it pays on.                                                                                                                                    | `same_variable_period`, `different_variable_or_period`, or a reason                                                                                         |
| `not_reproduced`     | Rebuilding the graph from these versions today does not yield the stored relation.                                                                                                                                                            |                                                                                                                                                             |
| `conclusion`         | The relation, from the left side.                                                                                                                                                                                                             | `relation` is set                                                                                                                                           |

Steps are emitted only where they apply: a within-venue ladder has no `game_quantity`; a cross-venue pair of the same event has no `same_event`. A step with a negative result ends the argument for that path, and the trail may still conclude by another (a cross-venue pair in one merged event, for instance).

## Reproduced or not

`reproduced` is `true` when running the graph's code over the stored contract versions of both markets and every market of their events yields the stored relation. It is `false` when it does not, usually because the venue changed metadata outside the rules hash since the relation was found. The trail then ends with:

```json theme={null}
{ "step": "not_reproduced", "detail": "Rebuilding the graph from these contract versions today does not yield the stored relation; source metadata outside the rules hash may have changed since. The evidence is as recorded when the relation was found." },
{ "step": "conclusion", "relation": "implies", "detail": "as recorded by graph run 53" }
```

Treat a relation that is not reproduced as one to check by hand before acting on it.

## Not found

| Status | `code`               | Meaning                                                                                             |
| ------ | -------------------- | --------------------------------------------------------------------------------------------------- |
| 400    | `invalid_market`     | A venue is not `kalshi` or `polymarket`, an id is malformed, or both markets are the same.          |
| 404    | `market_not_found`   | One or both markets are not in the latest graph.                                                    |
| 404    | `relation_not_found` | Both markets are in the latest graph, but no current proof relates their current contract versions. |

`relation_not_found` is the answer for two unrelated markets, and also for two markets that were related until one of them got a new contract version the graph has not yet related. `GET /v1/markets/{venue}/{id}/relations` lists what the latest graph does relate a market to.

## Example: a ladder within one venue

Two strikes on the same Kalshi spread event: "Aberdeen wins by more than 2.5 goals" and "by more than 1.5 goals".

```json theme={null}
{
  "data": {
    "relation": "implies",
    "graph_relation": "subset",
    "direction": "left_implies_right",
    "cross_venue": false,
    "left": {
      "venue": "kalshi",
      "id": "KXSCOTTISHPREMSPREAD-26SEP19HIBABE-ABE3",
      "event_id": "KXSCOTTISHPREMSPREAD-26SEP19HIBABE",
      "event_title": "Hibernian vs Aberdeen: Spread",
      "title": "Aberdeen wins by more than 2.5 goals?",
      "rules_hash": "1727a5c9b80d6fdd802d9ea61135ce3d75bd740d337bd0bb758e13ee370f71a0",
      "strike": { "type": "greater", "floor": "5/2", "custom": { "soccer_team": "\"6358a477-56ea-4ec9-bec9-59102e9d7573\"" }, "rules_template_hash": "15003fea…" },
      "variable": "strike of kalshi event KXSCOTTISHPREMSPREAD-26SEP19HIBABE, rules template 15003fea… with soccer_team=\"6358a477-…\"",
      "interval": "(2.5, ∞)",
      "settlement": { "payout_currency": "USD", "closes_at": "2026-09-21T14:00:00Z" },
      "first_seen_at": "2026-09-16T14:17:20.149996Z"
    },
    "right": {
      "venue": "kalshi",
      "id": "KXSCOTTISHPREMSPREAD-26SEP19HIBABE-ABE2",
      "title": "Aberdeen wins by more than 1.5 goals?",
      "rules_hash": "fbbb847892a6ad7cd14543ae5f81164c773d7b7e195fbef568462d486342a007",
      "strike": { "type": "greater", "floor": "3/2", "custom": { "soccer_team": "\"6358a477-56ea-4ec9-bec9-59102e9d7573\"" }, "rules_template_hash": "15003fea…" },
      "interval": "(1.5, ∞)"
    },
    "steps": [
      { "step": "same_event", "left": "KXSCOTTISHPREMSPREAD-26SEP19HIBABE", "right": "KXSCOTTISHPREMSPREAD-26SEP19HIBABE", "result": "same" },
      { "step": "same_variable", "detail": "same venue, custom strike terms and rules template with bounds masked", "left": "15003fea…", "right": "15003fea…", "result": "same" },
      { "step": "intervals", "left": "(2.5, ∞)", "right": "(1.5, ∞)", "result": "subset" },
      { "step": "conclusion", "relation": "implies" }
    ],
    "evidence": [ "exact strike bounds on one variable: same event, custom strike, bound-masked title, rules and settlement timing" ],
    "reproduced": true,
    "found_by": { "id": 53, "graph_version": "contract-graph/v1", "started_at": "2026-09-16T15:10:18.264674Z", "finished_at": "2026-09-16T15:10:37.648284Z" },
    "confirmed_by": { "id": 74, "graph_version": "contract-graph/v1", "started_at": "2026-09-17T12:10:17.023795Z", "finished_at": "2026-09-17T12:10:36.937979Z" },
    "first_seen_at": "2026-09-16T15:10:37.648284Z",
    "last_confirmed_at": "2026-09-17T12:10:36.937979Z"
  },
  "graph_run": 74
}
```

Both strikes sit on one variable, because they share an event, the same team in their custom terms and the same rules template once the bound is masked. (2.5, ∞) lies inside (1.5, ∞), so winning by more than 2.5 implies winning by more than 1.5. Some fields are trimmed above; `rules`, `yes_label`, `no_label` and the right side's `event_id` are returned in full.

## Example: a sports pair across venues

The 1.5-goal strike above against Polymarket's "Spread: Aberdeen FC (-1.5)":

```bash theme={null}
curl "https://api.routeur.app/v1/relations/kalshi/KXSCOTTISHPREMSPREAD-26SEP19HIBABE-ABE2/polymarket/scop-hib-abe-2026-09-19-spread-away-1pt5" \
  -H "X-API-Key: $ROUTEUR_API_KEY"
```

```json theme={null}
{
  "relation": "equivalent",
  "graph_relation": "equivalent",
  "direction": "both_ways",
  "cross_venue": true,
  "left": {
    "venue": "kalshi",
    "id": "KXSCOTTISHPREMSPREAD-26SEP19HIBABE-ABE2",
    "variable": "SCOTPREM margin of Aberdeen, Hibernian vs Aberdeen, 2026-09-19 ET",
    "interval": "(1.5, ∞)",
    "settlement": { "payout_currency": "USD", "scope": "90 minutes plus stoppage time, excluding extra time and penalties", "closes_at": "2026-09-21T14:00:00Z" }
  },
  "right": {
    "venue": "polymarket",
    "id": "scop-hib-abe-2026-09-19-spread-away-1pt5",
    "title": "Spread: Aberdeen FC (-1.5)",
    "yes_label": "Aberdeen FC",
    "no_label": "Hibernian FC",
    "strike": { "type": "greater", "floor": "3/2", "rules_template_hash": "b59c4ee3…" },
    "variable": "SCOTPREM margin of Aberdeen FC, Hibernian FC vs Aberdeen FC, 2026-09-19 ET",
    "interval": "(1.5, ∞)",
    "settlement": { "payout_currency": "USDC", "scope": "90 minutes plus stoppage time, excluding extra time and penalties", "closes_at": "2026-09-19T14:00:00Z", "game_starts_at": "2026-09-19T14:00:00Z" }
  },
  "steps": [
    { "step": "game_quantity", "left": "SCOTPREM margin of Aberdeen, Hibernian vs Aberdeen, 2026-09-19 ET", "right": "SCOTPREM margin of Aberdeen FC, Hibernian FC vs Aberdeen FC, 2026-09-19 ET", "result": "same_kind" },
    { "step": "same_game", "detail": "cross-venue: same scotprem game scheduled 2026-09-19 ET, matched by team codes and team names; both settle on 90 minutes plus stoppage time, excluding extra time and penalties; postponement and cancellation settle differently", "result": "same" },
    { "step": "orient_margin", "detail": "both contracts are on the same team's margin", "result": "same_subject" },
    { "step": "intervals", "left": "(1.5, ∞)", "right": "(1.5, ∞)", "result": "equivalent" },
    { "step": "conclusion", "relation": "equivalent" }
  ],
  "evidence": [ "cross-venue: same scotprem game scheduled 2026-09-19 ET, matched by team codes and team names; both settle on 90 minutes plus stoppage time, excluding extra time and penalties; postponement and cancellation settle differently" ],
  "reproduced": true,
  "found_by": { "id": 57, "graph_version": "contract-graph/v1", "started_at": "2026-09-16T19:10:18.079325Z", "finished_at": "2026-09-16T19:10:37.598821Z" },
  "confirmed_by": { "id": 74, "graph_version": "contract-graph/v1", "started_at": "2026-09-17T12:10:17.023795Z", "finished_at": "2026-09-17T12:10:36.937979Z" }
}
```

Both contracts are a margin of the same team in the same game, so no negation is needed and the intervals are identical: equivalent. Had Polymarket's line been on Hibernian, `orient_margin` would report `negated` with the flipped interval on the `right`, and the `intervals` step would compare (1.5, ∞) with (−∞, −1.5): `contradicts`. A total (over/under) pair has no `orient_margin` step at all, because a total has no side.

The `same_game` detail is worth reading: the venues match on 90 minutes plus stoppage time, but "postponement and cancellation settle differently", which is why a [lead](/concepts/leads) on such a pair carries an issue.

## Example: an economics pair across venues

A Kalshi strike ladder and a Polymarket bucket question on one economic or crypto variable (a Fed target-range bound, a price of Bitcoin or Ether) take a different path, since Polymarket carries no structured strike there and its range is read from the question. The steps are, in order:

```json theme={null}
{ "step": "econ_quantity", "left": "fomc_target_range_upper_bound for 2026-12", "right": "fomc_target_range_upper_bound for 2026-12", "result": "same_variable_period" },
{ "step": "same_variable", "detail": "…", "result": "same" },
{ "step": "intervals", "left": "(4, 4.25]", "right": "[4, 4.25]", "result": "equivalent", "detail": "the question leaves bound inclusivity open; the relation holds under every convention" },
{ "step": "conclusion", "relation": "equivalent" }
```

Each contract's `settlement.scope` then reads `settles on <source>, observed at <time>`, and the `same_variable` detail says how the two observations line up. When a bucket's inclusivity is only implied by the question, the `intervals` step passes only if the relation holds under every convention; otherwise its result is `ambiguous` and there is no conclusion.

<Note>
  At the time of writing the latest graph contains no economics pair across venues (every one of its 4,400 cross-venue pairs is a sports line), so the fragment above shows the shape the code produces rather than an observed response. Pairs appear as soon as both venues list matching contracts.
</Note>

## Related

* [Relations](/concepts/relations): what each relation means and how one is proven.
* [Cross-venue pairs](/concepts/cross-venue): finding pairs to open up.
* [Rules](/concepts/rules): the contract versions a proof is pinned to.
* [Live stream](/concepts/live-stream): every new relation arrives with its `proof_path`.
