Skip to content

Change plan, interval or add-on

POST
/v1/billing/change
curl --request POST \
--url https://oddslink.app/v1/billing/change \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "plan": "api_scale", "interval": "month" }'

Signed-in website session only; the body is the same as checkout. A bigger plan, or a move from monthly to yearly, is charged the difference to the saved card now and takes effect at once (charged_cents is what was charged). A smaller plan, a move from yearly to monthly, or turning the add-on off waits for the next renewal and shows up as pending_change, with charged_cents 0. A subscription whose last renewal failed must have its card updated first.

Media typeapplication/json
object
plan
required

The plan. api_free is not accepted, because it costs nothing.

string
Allowed values: api_starter api_growth api_scale api_business
interval

Billing period. Yearly is the same ladder at a 20% discount.

string
default: month
Allowed values: month year
addon

Include the live-feed add-on. Accepted only with api_growth and api_scale.

boolean
Examples
ExamplescaleMonthly

Move to Scale, billed monthly

{
"plan": "api_scale",
"interval": "month"
}

The subscription after the change, and what was charged now.

Media typeapplication/json
object
subscription
required

An account’s subscription. The card is described only by its last four digits.

object
plan
required

A plan slug, for example api_growth. New plans may be added.

string
interval
required

month or year.

string
addon
required

Whether the live-feed add-on is included.

boolean
status
required

active, or past_due when the last renewal failed and the card must be updated.

string
current_period_start
required
string format: date-time
current_period_end
required
string format: date-time
cancel_at_period_end
required
boolean
pending_change
required

A change that takes effect at the next renewal.

object
plan
required

A plan slug, for example api_growth.

string
interval
required

month or year.

string
addon
required
boolean
card_last4
required
string | null
amount_cents
required

What one renewal charges, in cents.

integer
next_charge_at
required
string | null format: date-time
charged_cents
required

Cents charged to the saved card by this change. 0 when the change waits for the renewal.

integer
Example
{
"subscription": {
"plan": "api_growth",
"interval": "year",
"addon": false,
"status": "active",
"current_period_start": "2026-09-30T00:00:00.000Z",
"current_period_end": "2027-09-30T00:00:00.000Z",
"cancel_at_period_end": false,
"pending_change": null,
"card_last4": "4242",
"amount_cents": 47000,
"next_charge_at": "2027-09-30T00:00:00.000Z"
},
"charged_cents": 0
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

A parameter was malformed.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Example
{
"error": {
"code": "BAD_REQUEST",
"message": "commenceTimeFrom is not a valid ISO-8601 timestamp.",
"docs_url": "https://oddslink.app/docs/errors/#bad-request",
"request_id": "req_01hz8k3z9e2v6w1x"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

The Authorization bearer session is missing or invalid.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Examples

No Authorization: Bearer header sent

{
"error": {
"code": "MISSING_SESSION",
"message": "Sign in and try again.",
"docs_url": "https://oddslink.app/docs/errors/#missing-session",
"request_id": "req_01hz8k4b9h5y0z1a"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

The saved card was declined. Nothing was changed.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Example
{
"error": {
"code": "PAYMENT_DECLINED",
"message": "the card was declined; nothing was changed",
"docs_url": "https://oddslink.app/docs/errors/#payment-declined",
"request_id": "req_01J8Z5Q2K9V3N7M4"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

This account has no subscription.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Example
{
"error": {
"code": "NO_SUBSCRIPTION",
"message": "this account has no subscription",
"docs_url": "https://oddslink.app/docs/errors/#no-subscription",
"request_id": "req_01J8Z5Q2K9V3N7M4"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

The last renewal failed (PAYMENT_PAST_DUE, update the card first), or another billing change is in progress (BILLING_BUSY, try again shortly).

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Examples

The last renewal failed

{
"error": {
"code": "PAYMENT_PAST_DUE",
"message": "update your card before changing plan",
"docs_url": "https://oddslink.app/docs/errors/#payment-past-due",
"request_id": "req_01J8Z5Q2K9V3N7M4"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

The plan’s speed limit was exceeded; wait Retry-After seconds. A call that does not count against the allowance is never refused for a spent allowance.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Example
{
"error": {
"code": "SPEED_LIMIT",
"message": "Speed limit exceeded: 10 requests/second on the Growth plan.",
"docs_url": "https://oddslink.app/docs/errors/#speed-limit",
"request_id": "req_01hz8k4f7m9c3d8f"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

Retry-After
integer

Seconds to wait before retrying on 429 SPEED_LIMIT or 503 ODDS_UNAVAILABLE.

The billing provider could not be reached.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Example
{
"error": {
"code": "BILLING_UNAVAILABLE",
"message": "could not reach the billing provider; try again",
"docs_url": "https://oddslink.app/docs/errors/#billing-unavailable",
"request_id": "req_01J8Z5Q2K9V3N7M4"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

Billing is not configured on this deployment. Fails closed rather than taking money it cannot then account for.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Example
{
"error": {
"code": "BILLING_NOT_CONFIGURED",
"message": "billing is not configured on this deployment",
"docs_url": "https://oddslink.app/docs/errors/#billing-not-configured",
"request_id": "req_01J8Z5Q2K9V3N7M4"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.

Something failed on our side.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
docs_url
required
string format: uri
request_id
required
string
stored_commence_times

Stored Unix-second choices on AMBIGUOUS_EVENT or INVALID_STORED_COMMENCE_TIME; independent of dateFormat.

Array<integer>
valid_bookmakers

Valid case-sensitive book keys on INVALID_BOOKMAKER.

Array<string>
current_plan

403 only: the plan on the presented key.

string
required_plan

403 only: the lowest plan that includes this request. For history, that depends on how long ago the fixture started as well as on the endpoint.

string
Example
{
"error": {
"code": "INTERNAL_ERROR",
"message": "Something went wrong on our side. It has been logged.",
"docs_url": "https://oddslink.app/docs/errors/#internal-error",
"request_id": "req_01hz8k4h8n0d4e9f"
}
}
x-requests-used
integer

Requests used this billing period.

x-requests-remaining
integer

Requests remaining this billing period.

x-requests-last
integer

What this one call cost against the allowance (0 for a free call).

X-RateLimit-Limit
integer

This plan’s speed limit, in requests per second.

X-RateLimit-Remaining
integer

Requests left in the current one-second window.

X-RateLimit-Reset
integer

Seconds until the speed-limit window resets.

X-Request-Id
string

This request’s id, for support and for matching against error.request_id.