POST /v3/place_betAsynchronous bet placement. Returns 202 Accepted in ~100 ms with a correlation_id; the actual bet result is delivered via polling or a webhook.
correlation_id contract, and has the copy-paste CLAUDE.md snippet for AI assistants. All /v3/* endpoints follow the same model.Important. Use
POST /v3/place_bet(async). The synchronous/v2/place_betis deprecated — it holds the HTTP connection open up to 30s and 504s frequently. Hitting it now returns410 Gonewith a pointer to v3:{ "error": "deprecated", "use": "POST /v3/place_bet" }
X-API-Key: <your-api-key>
Content-Type: application/json
Every request must also include a session_id belonging to the account that
owns the API key.
curl -X POST https://api.b337.ai/v3/place_bet \ -H "X-API-Key: <your-key>" \ -H "Content-Type: application/json" \ -d '{ "session_id": "11142", "category": "racing", "track": "Flemington", "race_num": 4, "race_type": "(R)", "date": "2026-05-25", "runner": "Verry Elleegant", "market": "win", "stake": 25.00, "target_odds": 4.20 }'
Response (202):
{ "status": "pending", "correlation_id": "9b3c…uuid…", "submitted_at": "2026-05-25T03:11:00.000Z", "timeout_at": "2026-05-25T03:12:00.000Z" }
Set is_same_event_multi: true and pass a legs array. runner /
market move into each leg.
{ "session_id": "11142", "category": "racing", "track": "Flemington", "race_num": 4, "date": "2026-05-25", "is_same_event_multi": true, "legs": [ { "runner": "Verry Elleegant", "market": "win" }, { "runner": "Nature Strip", "market": "place" } ], "stake": 10.00, "target_odds": 12.00 }
For stacked SRMs (TAB only) see the dedicated
POST /v3/stacked_srm endpoint.
Exacta, Quinella, Duet, Trifecta, First 4 and the multi-race pools (Quaddie,
Treble, Big 6, …) are a separate category — category: "exotic", with
legs that are RACES rather than selections, and no price at all. See the
Exotics tab above.
| Field | Type | Required | Notes |
|---|---|---|---|
session_id | string | ✅ | Must belong to caller's API key and be active. |
category | "racing" | ✅ | Constant. |
track | string | ✅ | e.g. "Flemington", "Randwick". |
race_num | int | ✅ | Race number. |
race_type | string | optional | "(R)" thoroughbred (default), "(G)" greyhound, "(H)" harness. |
country | string | recommended | Region code — "au", "nz", "gb", "us", … Send it together with date and we resolve the exact race against our race spine and match the bookmaker's exact track naming — this disambiguates same-named tracks across regions and days. Omit it and we fall back to looser name matching. |
date | string | ✅ | YYYY-MM-DD — the race's actual date. Supply it (with country) so we never match the wrong day. |
runner | string | single only | Runner name as the bookie lists it. |
market | string | single only | "win" or "place". each_way is not supported and will 400. |
is_same_event_multi | bool | for SRM | If true, supply legs[] instead of runner/market. |
legs | array | for SRM | [{ runner, market }, …]. |
stake | number | ✅ | Dollars. |
target_odds | number | ✅ | Floor — bet rejected below this. |
max_odds | number | optional | Ceiling — bet auto-rejected if the live matched price is above this. Guards against wrong-line / wrong-runner matching. Omit / null = no ceiling. Must be ≥ target_odds. |
use_boost | bool | optional | Apply an odds boost if available. |
betboost | bool | optional | Apply a boost opportunistically: attach one if the bookie offers it, otherwise place the bet unboosted. use_boost is strict and refuses a bet it cannot boost. |
use_bonus_bet | bool | optional | Use bonus-bet balance. |
promo_name | string | optional | Specific promo to attach. |
skip_if_no_promo | bool | optional | If true, reject the bet when the promo isn't applicable instead of placing without it. |
callback_url | string | optional | Webhook for async result. |
random_delay | object | optional | { min, max } — seconds the client waits before placing, drawn as random.uniform(min, max). Floats allowed (e.g. 0.5). min defaults to 0; the delay is only applied when max > 0 (omit / max: 0 = no delay). |
| Status | Body | Meaning |
|---|---|---|
| 400 | {"error":"market not supported","market":"each_way"} | Use win or place. |
| 403 | {"error":"session_not_owned"} | The session_id doesn't belong to this API key's account. |
| 410 | {"error":"deprecated","use":"POST /v3/place_bet"} | You hit /v2/place_bet. Migrate. |