Reference

Errors

All error responses share the shape {"error":{"code","message"}}. Match on error.code, not on the message text — messages may change for clarity. Some errors add optional links: upgradeUrl and docsUrl.

Error shape

Every non-2xx response from /api/v1 carries a stable machine-readable code under error.code. Build your retry and alerting logic against that field.

Entitlement and quota errors are actionable. A 403 forbidden for a bookmaker your plan does not include carries error.upgradeUrl (the billing page on app.betspread.io) and error.docsUrl (this reference). The monthly-quota 429 rate_limit_exceeded carries error.upgradeUrl. Both fields are optional: other errors omit them, so treat them as hints and ignore unknown fields.

{
  "error": {
    "code": "forbidden",
    "message": "No product-verified bookmaker entitlements available for this sport and transport",
    "upgradeUrl": "https://app.betspread.io/dashboard/billing",
    "docsUrl": "https://betspread.io/docs/errors#forbidden"
  }
}

Error codes

missing_api_key401

No Authorization header and no X-Api-Key header was supplied.

invalid_api_key401

Credential is rejected (unknown, expired, or revoked).

validation_failed400

A query or path parameter failed validation (e.g. unknown sport, non-numeric eventId, limit out of range, duplicate bookmaker filter).

forbidden403

Authenticated but no product-verified bookmaker entitlement for the requested sport and transport. The body adds upgradeUrl (billing page on app.betspread.io) and docsUrl (this entry); compare your plan's bookmakers there or request fewer bookmakers.

live_not_enabled403

Caller requested transport=live but plan entitlement does not include the Live channel.

api_key_scope_denied403

The API key is restricted and does not allow the requested product channel, bookmaker, or sport. Use an unrestricted key or create a key whose scope includes the requested REST/Live/History channel, sport, and bookmaker.

not_found404

Well-formed numeric eventId, but the event does not exist or is not visible to your organization.

rate_limit_exceeded429

Hourly rate limit or monthly REST quota exhausted. Use X-RateLimit-Reset and Retry-After before retrying. The monthly-quota variant adds upgradeUrl (billing page) for a higher quota.

service_unavailable503

Required auth, quota, or rate-limit backend is unavailable; the public API fails closed.