Opono
Skip to content
Documentation menu Simulations ▾

API reference

Simulations

Copy as Markdown

Create a simulation

POST /v1/simulations

Simulate one match for exactly draws / 1,000 credits per live delivery, including cached results.

Authentication: Bearer API key with simulations.run; active Plus or Pro plan required.

Parameters

Send an optional Idempotency-Key header (1–255 characters) and keep the same key and exact JSON body for retries.

Path parameters

NameTypeRequiredDescription
———None.

Query parameters

NameTypeRequiredDescription
———None.

Body parameters

NameTypeRequiredDescription
fixture_idinteger or stringConditionalUse a returned fixture ID instead of home, away, and date.
homestringConditionalHome team name; required with away when you omit fixture_id; maximum length: 200.
awaystringConditionalAway team name; required with home when you omit fixture_id; maximum length: 200.
drawsintegerNoNumber of simulated matches: full simulated playthroughs of the fixture; range: 100–1,000,000; default: 1,000.
datestringNoFixture date in YYYY-MM-DD format; omit it to select the next match.
wait_secondsintegerNoMaximum time to wait for a result before returning a job; range: 0–25; default: 25.
lineupsobjectNoOptional home and away source choices: auto (default), predicted, announced, or custom; see Choosing lineups.

Example request

bash
curl --request POST 'https://api.opono.com/v1/simulations' \
  --header "Authorization: Bearer $OPONO_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: match-example-1' \
  --data '{"fixture_id":19609874,"draws":1000}'

Response

FieldTypeDescription
objectstringsimulation for delivery; simulation_job for pending or terminal jobs.
idstringDelivered simulation ID.
fixture_idintegerResolved fixture ID.
statestringprovisional, inputs_final, or lineups_announced.
data_versionstringOpaque input version; compare it only for equality.
created_atstringSimulation creation time in ISO 8601 UTC.
livemodebooleanFalse for synthetic test output.
price.drawsintegerNumber of simulated matches for this simulation.
price.creditsstringExact credit price with three decimal places.
credits_chargednumberCredits settled for this request; zero in test mode.
scopestringshared or private; private results belong only to your organisation.
inputs.lineupsobjectResolved home and away sources; custom sides include normalized XI, bench and formation. Announced sides show only source.
inputs.squad_versionstringSquad version used to validate your lineups.
warningsarrayNon-blocking low_start_probability, goalkeeper_unverified, or official_lineups_announced warnings.
receiptobjectRequest ID, idempotency key, price, charged credits, and remaining credits.
receipt.inputs_hashstring or nullThe run's input fingerprint; null on older receipts.
simulationobjectThe opono.simulation.v1 document; see the fields below.
simulation.fixtureobjectFixture ID, kick-off, competition, and both team labels.
simulation.basisobjectInput state, as_of timestamp, data_version, lineups, number of simulated matches (draws), and seed.
simulation.basis.lineupsstringpredicted, announced, or custom; this enum can gain values.
simulation.basis.lineup_sourcesobjectOptional home and away sources: predicted, announced, or custom; absent on older results.
simulation.resultobjectHome win, draw, and away win probabilities from 0 to 1.
simulation.goalsobjectExpected goals, score grid, and goal distributions.
simulation.marketsobjectScorelines, totals, and both-teams-to-score probabilities.
simulation.half_timeobjectHalf-time and joint half-time/full-time probabilities.
simulation.timelineobject110 steps with minute_label, team event series, and score-state probabilities.
simulation.goal_eventsobjectFirst-goal, first-scorer, and comeback probabilities when present.
simulation.playersarrayPer-player probabilities, expected minutes, and box-score statistics.
simulation.lineupsobjectStarting elevens and benches used for each side when present.
simulation.samplesarray20 illustrative match paths when present.
simulation.uncertaintyobjectNumber of simulated matches, Monte Carlo estimates, and model-accuracy status.
simulation.modelobjectPublic model name, version, and qualification status.
simulation.timingobjectSimulation duration when present.

Example response

200 test response (excerpt); see OpenAPI for the full schema.

json
{
  "object": "simulation",
  "fixture_id": 19609874,
  "state": "provisional",
  "data_version": "2026-10-13:predicted:b167bda637016662e2585f872b25dea30f954c9a56bd5a345ff965b1663eee10",
  "livemode": false,
  "credits_charged": 0,
  "simulation": {
    "schema": "opono.simulation.v1",
    "basis": {
      "as_of": "2026-10-12T18:30:00Z",
      "data_version": "2026-10-13:predicted:b167bda637016662e2585f872b25dea30f954c9a56bd5a345ff965b1663eee10"
    },
    "result": {
      "home": 0.47,
      "draw": 0.26,
      "away": 0.27,
      "calibrated": true
    },
    "goals": {
      "expected": {
        "home": 1.69,
        "away": 1.27
      }
    },
    "model": {
      "public_name": "Opono Robin",
      "status": "unqualified"
    }
  },
  "price": {
    "draws": 1000,
    "credits": "0.000"
  }
}

202 response.

json
{
  "object": "simulation_job",
  "job_id": "job_example",
  "fixture_id": 19609874,
  "reservation_id": "reservationexample",
  "result_url": "/v1/simulations/jobs/job_example?reservation_id=reservationexample",
  "status": "queued",
  "price": {
    "draws": 1000,
    "credits": "1.000"
  },
  "credits_reserved": 1,
  "retry_after_seconds": 10
}

Errors

StatusCodeMeaning
400parameter_invalidA parameter has an invalid value.
401invalid_api_keyThe credential cannot authenticate.
401key_revokedThe API key has been revoked.
401key_expiredThe API key has expired.
403scope_missingThe key lacks the required scope.
403tier_restrictedThe organisation plan does not include this operation.
403org_suspendedYour account is suspended.
403ip_not_allowedThe caller is outside the key's IP allowlist.
429rate_limitedA request or authentication rate limit was exceeded.
503dependency_unavailableRequest admission is unavailable.
503maintenanceThe API is paused for maintenance.
402balance_too_lowYour available balance cannot cover the request.
404fixture_not_foundNo matching simulation fixture exists.
409fixture_ambiguousThe fixture lookup identifies multiple candidates.
503fixture_lookup_incompleteThe fixture lookup could not prove a unique match.
409idempotency_conflictAn idempotency key conflicts with a prior request.
429concurrency_limitedThe organisation has no available concurrent slot.
429loop_guardA repeated-call burst was refused.
400fixture_not_coveredThe requested fixture is not available for simulation.
503refreshingThe request can't be checked right now.
503settlement_unknownDelivery settlement could not be confirmed.
400lineup_invalidThe custom XI, bench, goalkeeper selection, or formation is invalid; recovery.reason identifies the rule.
400player_not_in_squadA custom player ID is outside this side's squad; check recovery.unknown_id against the free squads list.
409lineups_not_announcedAnnounced team sheets are unavailable; wait for publication or use auto.
429lineup_cooldownCustom-lineup requests are temporarily locked; wait for Retry-After and recovery.retry_at.

Quote a simulation

POST /v1/simulations/quote

Get the exact price without running a simulation or reserving credits. Non-auto sources also validate lineups against current fixture inputs; that validation holds while squad_version and data_version remain unchanged.

Authentication: Bearer API key with simulations.run; active Plus or Pro plan required.

Parameters

Path parameters

NameTypeRequiredDescription
———None.

Query parameters

NameTypeRequiredDescription
———None.

Body parameters

NameTypeRequiredDescription
fixture_idinteger or stringConditionalUse a returned fixture ID instead of home, away, and date.
homestringConditionalHome team name; required with away when you omit fixture_id; maximum length: 200.
awaystringConditionalAway team name; required with home when you omit fixture_id; maximum length: 200.
drawsintegerNoNumber of simulated matches: full simulated playthroughs of the fixture; range: 100–1,000,000; default: 1,000.
datestringNoFixture date in YYYY-MM-DD format; omit it to select the next match.
wait_secondsintegerNoMaximum time to wait for a result before returning a job; range: 0–25; default: 25.
lineupsobjectNoOptional home and away source choices: auto (default), predicted, announced, or custom; see Choosing lineups.

Example request

bash
curl --request POST 'https://api.opono.com/v1/simulations/quote' \
  --header "Authorization: Bearer $OPONO_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{"fixture_id":19609874,"draws":1000}'

Response

FieldTypeDescription
objectstringsimulation_quote.
price.drawsintegerRequested number of simulated matches.
price.creditsstringExact credit price; zero in test mode.
creditsnumberNumeric credit price.
credits_chargednumberAlways zero.
rate_cardstringPrice revision.
livemodebooleanFalse for a test key.
scope / inputs / warningsstring / object / arrayProposed run scope, normalized lineup inputs and non-blocking warnings when present.

Example response

200 response.

json
{
  "object": "simulation_quote",
  "price": {
    "draws": 1000,
    "credits": "1.000"
  },
  "credits": 1,
  "credits_charged": 0,
  "rate_card": "draws-2026-10-13",
  "livemode": true
}

Errors

StatusCodeMeaning
400parameter_invalidA parameter has an invalid value.
401invalid_api_keyThe credential cannot authenticate.
401key_revokedThe API key has been revoked.
401key_expiredThe API key has expired.
403scope_missingThe key lacks the required scope.
403tier_restrictedThe organisation plan does not include this operation.
403org_suspendedYour account is suspended.
403ip_not_allowedThe caller is outside the key's IP allowlist.
429rate_limitedA request or authentication rate limit was exceeded.
503dependency_unavailableRequest admission is unavailable.
503maintenanceThe API is paused for maintenance.
400lineup_invalidThe custom XI, bench, goalkeeper selection, or formation is invalid; recovery.reason identifies the rule.
400player_not_in_squadA custom player ID is outside this side's squad; check recovery.unknown_id against the free squads list.
409lineups_not_announcedAnnounced team sheets are unavailable; wait for publication or use auto.
429lineup_cooldownCustom-lineup requests are temporarily locked; wait for Retry-After and recovery.retry_at.
404fixture_not_foundNo matching simulation fixture exists.
400fixture_not_coveredThe requested fixture is not available for simulation.
503refreshingThe request can't be checked right now.

Create a batch

POST /v1/simulations/batch

Reserve credits for up to 1,000 matches before queuing them; each delivered item costs draws / 1,000 credits.

Authentication: Bearer API key with simulations.run; active Plus or Pro plan required.

Parameters

Send an optional Idempotency-Key header (1–255 characters) and keep the same key and exact JSON body for retries.

Path parameters

NameTypeRequiredDescription
———None.

Query parameters

NameTypeRequiredDescription
———None.

Body parameters

NameTypeRequiredDescription
fixturesarrayYesDistinct match selectors; each uses fixture_id or home and away with an optional date; items: 1–1,000.
fixtures[].fixture_idinteger or stringConditionalFixture ID; omit team names and date when you use it.
fixtures[].homestringConditionalHome team name; required without fixture_id; maximum length: 200.
fixtures[].awaystringConditionalAway team name; required without fixture_id; maximum length: 200.
fixtures[].datestringNoOptional fixture date in YYYY-MM-DD format.
fixtures[].lineupsobjectNoOptional per-side lineup choices for this item; all items are validated before reserving credits.
drawsintegerNoNumber of simulated matches: full simulated playthroughs of the fixture; range: 100–1,000,000; default: 1,000.

Example request

bash
curl --request POST 'https://api.opono.com/v1/simulations/batch' \
  --header "Authorization: Bearer $OPONO_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: match-example-1' \
  --data '{"fixtures":[{"fixture_id":19609874}],"draws":1000}'

Response

FieldTypeDescription
objectstringsimulation_batch.
batch_idstringYour batch ID.
itemsarrayPer-fixture jobs and reservations.
items[].fixtureintegerFixture ID.
items[].job_idstringJob ID for this fixture.
items[].statusstringCurrent item status.
items[].credits_reservednumberCredits held for this item.
items[].reservation_idstringRequest-bound reservation when present on submission.
items[].result_urlstringFollow this path to deliver and settle the item.
items[].errorobjectError code and message when an item is unavailable.
items[].credits_chargednumberSettled credits when present on a status response.
items[].freshnessobjectFreshness state and check times when present on a status response.
items[].scope / inputs / warningsstring / object / arrayEach item's run scope, normalized inputs and lineup warnings when present.
validUntilnumber or nullEarliest item freshness deadline in Unix milliseconds when present.
credits_reserved_totalnumberTotal credits reserved for this batch when present.

Example response

202 response; the JSON body must fit within 2 MiB.

json
{
  "object": "simulation_batch",
  "batch_id": "batch_example",
  "items": [
    {
      "fixture": 19609874,
      "job_id": "job_example",
      "status": "queued",
      "credits_reserved": 1,
      "reservation_id": "reservationexample",
      "result_url": "/v1/simulations/jobs/job_example?reservation_id=reservationexample"
    }
  ],
  "credits_reserved_total": 1
}

Errors

StatusCodeMeaning
400parameter_invalidA parameter has an invalid value.
401invalid_api_keyThe credential cannot authenticate.
401key_revokedThe API key has been revoked.
401key_expiredThe API key has expired.
403scope_missingThe key lacks the required scope.
403tier_restrictedThe organisation plan does not include this operation.
403org_suspendedYour account is suspended.
403ip_not_allowedThe caller is outside the key's IP allowlist.
429rate_limitedA request or authentication rate limit was exceeded.
503dependency_unavailableRequest admission is unavailable.
503maintenanceThe API is paused for maintenance.
402balance_too_lowYour available balance cannot cover the request.
404fixture_not_foundNo matching simulation fixture exists.
409fixture_ambiguousThe fixture lookup identifies multiple candidates.
503fixture_lookup_incompleteThe fixture lookup could not prove a unique match.
409idempotency_conflictAn idempotency key conflicts with a prior request.
429concurrency_limitedThe organisation has no available concurrent slot.
429loop_guardA repeated-call burst was refused.
400fixture_not_coveredThe requested fixture is not available for simulation.
503refreshingThe request can't be checked right now.
503settlement_unknownDelivery settlement could not be confirmed.
400lineup_invalidThe custom XI, bench, goalkeeper selection, or formation is invalid; recovery.reason identifies the rule.
400player_not_in_squadA custom player ID is outside this side's squad; check recovery.unknown_id against the free squads list.
409lineups_not_announcedAnnounced team sheets are unavailable; wait for publication or use auto.
429lineup_cooldownCustom-lineup requests are temporarily locked; wait for Retry-After and recovery.retry_at.