---
title: "Market intelligence on one race: consensus at fixed marks, time-anchored moves, breadth, first mover, signal"
method: GET
path: "/v1/racing/intelligence"
tags: ["Racing"]
---

# Market intelligence on one race: consensus at fixed marks, time-anchored moves, breadth, first mover, signal

`GET /v1/racing/intelligence`

## Request

- Base URL: `https://api.puntersedge.online`
- URL: `https://api.puntersedge.online/v1/racing/intelligence`
- Auth: API key in header `X-API-Key`

Cost: 3 credits. One race on the live board: for every runner, the market consensus
price now and at fixed marks before the jump (T-60, T-30, T-15, T-10, T-5, T-2), its high
and low since capture began, movement measured against those marks and against the last
five and two minutes, the number of ticks in the last five minutes, the best price against
the consensus, how many books moved with the headline, the first attributable book to move,
and a signal class whose rule is printed in the response.

**Naming the race.** `race_id` from /v1/racing/next-to-go or /v1/racing/events is exact.
Failing that, `venue` + `meeting_date` (AET) + `race_number`, with `country` when two
meetings share the name on one date; a venue split answers 409, naming each race, and
costs nothing.

**Time-anchored, not open-anchored.** Every movement figure compares the consensus NOW with
the consensus at a fixed time, computed by the same arithmetic as GET /v1/racing/consensus
and the archive's consensus columns: each book's win prices with its margin removed, the
median across books, the field scaled to one. `move_from_t60_pct` is negative for a runner
that shortened. A mark is null when the race had not entered the capture window by then —
capture begins 60 minutes before the jump, so a race further out than that carries `now`
only and `window.open` is false.

**Breadth.** `with_history` counts books quoting now with two or more captured prices on
the runner; `firming`, `drifting` and `unchanged` partition them by each book's own price
against its price at T-60 (or its first tick, when it joined later). A headline move that
most of `with_history` did not make is one book repricing, not the market.

**First mover** names the earliest attributable book to move at least 5 % in the headline
direction, with its lead over the next book and the median lag of the followers. It is
`undetermined` when fewer than two attributable books moved or when the lead is inside the
30-second attribution floor (the books are polled every 8–17 seconds). Books whose
timestamps cannot order a move are excluded and named in `method`: push-fed books (the stamp
is the receipt, not the read) and books polled slower than the floor.

**Signal** is one of `strong_firm`, `firm`, `steady`, `drift`, `strong_drift` or
`insufficient`, from `move_from_t60_pct` and the breadth, by the rule in `method.signal_rule`.
It is a classification of what the market did, not a prediction; its strike rate against
results will be published on the market report once the archive carries it.

**Live only.** A race that has left the live board answers 404; a race inside the ten
minutes after its jump is still served while the books drop off, with a note.

Every plan, Free included. 3 credits, charged after the race is found.

## Query parameters

- `race_id` string, nullable: The race_id from /v1/racing/next-to-go or /events.
- `venue` string, nullable: Venue as the feeds spell it; needs meeting_date and race_number.
- `meeting_date` string, date, nullable: AET meeting date, YYYY-MM-DD.
- `race_number` integer, nullable
- `country` string, nullable: Alpha-2 country of the meeting (AU, NZ, GB, IE, ZA, ...). Only needed with venue when two meetings share the name on one AET date — Ascot (Perth) and Ascot (Berkshire) on 17 October 2026 — and the 409 names each candidate's country.
- `min_books` integer: Included books a runner needs before it carries a consensus at a mark.

## Headers

- `X-API-Key` string
- `X-RapidAPI-Proxy-Secret` string

## Response `200`

Successful Response

- IntelOut
  - `race` IntelRaceOut, required
    - `race_id` string, required
    - `venue` string, nullable
    - `race_number` integer, nullable
    - `category` string, nullable
    - `country` string, nullable
    - `start_time` string, nullable
    - `secs_to_jump` integer, nullable
    - `status` string: upcoming · jumped.
    - `as_of` string, required
  - `window` object: Whether the 60-minute capture window is open for this race, when its first tick landed, and which marks could be evaluated.
  - `method` object, required
  - `market` object: Race level: best-price market percentage now and at T-15 / T-60, the favourite now and at T-10, and the books behind the consensus.
  - `runners` object[]: One object per runner, favourite first: consensus at each mark with high and low, time-anchored moves, breadth, first mover and the signal class.
  - `scratchings` object[]
  - `note` string, nullable

## Other responses

- `401`: Missing or invalid API key. Send `X-API-Key`. See https://puntersedge.online/developers/errors
- `402`: Monthly credit allowance exhausted for this plan. Upgrade at https://puntersedge.online/api/pricing
- `404`: No race on the live board matched. Nothing was charged.
- `409`: Two races share that venue, date and number; the body names each one. Pass country= or race_id. Nothing was charged.
- `422`: Unparseable parameter or unknown bookmaker key. Nothing was charged.
- `429`: Rate limit exceeded for this plan. Honour the `Retry-After` header (seconds) before retrying. See https://puntersedge.online/developers/rate-limits
- `500`: Unexpected server error. Safe to retry with backoff.

---

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