Skip to content
Coritan Docs

Rate limits

How many requests the Coritan API accepts, the tighter limits on sign-in and some actions, and how to handle a 429 response.

View as Markdown

The Coritan API limits how many requests it takes from one address, how many failed sign-ins it accepts, and how often you can repeat an action that costs a lot to carry out. A request over any limit answers 429 Too Many Requests, and the Retry-After header says how many seconds to wait.

Limit What it counts Answer
2,400 requests a minute Every API request from one IP address in the last 60 seconds 429 with {"detail": "Rate limit exceeded"}. Retry-After is the number of seconds until the oldest of those requests is a minute old.
200 requests a second, in bursts of up to 400 Every request from one IP address, counted by the proxy in front of the API 429 with {"error":"Too many requests"} and Retry-After: 1.
128 connections Open connections from one IP address to the proxy The proxy closes a new connection without an answer.

The proxy's limits are its defaults, and Coritan can change them. When the proxy refuses 8 requests in a row from one address, it blocks that address for 5 minutes. While the block lasts, every request answers 429 and every new connection is closed, so do not retry at once after a 429.

Only failures count towards these limits: an answer of 401 or 403. A sign-in that works costs nothing.

Limit Routes Answer
40 failed attempts a minute, from one IP address, on each route POST /auth/login, POST /auth/register and POST /auth/refresh; on an organization, POST /orgs/{org_slug}/auth/login, /auth/register and /auth/forgot-password, and POST /orgs/{org_slug}/staff/auth/login and /staff/auth/forgot-password 429 with {"detail": "Too many authentication attempts. Please try again later."} and Retry-After: 60.

POST /auth/forgot-password always answers 200, so it has a budget that counts every request instead: 10 in 15 minutes from one IP address, and 3 in 15 minutes for one email address. Checking a two-factor code has one too, as the next table shows.

These actions start work that takes time or resources on Coritan's side, so each has a budget of its own on top of the limits above. The budget counts your requests for one server, instance or route, or for your whole account where the table says so.

Action Routes Budget
container.power POST /client/servers/{uuid}/power 24 a minute
container.wake POST /client/servers/{uuid}/wake 48 a minute
container.backup POST /client/servers/{uuid}/backups 8 in 5 minutes
container.backup_restore POST /client/servers/{uuid}/backups/{backup_uuid}/restore 8 in 5 minutes
container.file_compress POST /client/servers/{uuid}/files/compress and /files/decompress 24 a minute
container.file_pull POST /client/servers/{uuid}/files/pull 24 a minute
container.import POST /client/servers/{uuid}/import/start and /import/test-connection 12 in 5 minutes
container.software The routes under /client/servers/{uuid}/software/ that install, change or update software 8 in 10 minutes
container.database POST /client/servers/{uuid}/databases 24 a minute
vps.power POST /client/vps/{uuid}/power 24 a minute
vps.rebuild POST /client/vps/{uuid}/rebuild 8 in 10 minutes
vps.backup POST /client/vps/{uuid}/backups 8 in 5 minutes
vps.backup_restore POST /client/vps/{uuid}/backups/{backup_id}/restore 8 in 5 minutes
custom_domain.link POST /client/external-servers/{service_id}/custom-domain and POST /gameproxy/routes/{route_id}/custom-domain 12 an hour
custom_domain.verify The same two routes with /verify added 12 an hour
external_server.update PATCH /client/external-servers/{service_id} 30 in 5 minutes
external_server.probe POST /client/external-servers/{service_id}/test 20 a minute, for your account
platform_domains.availability GET /client/platform-domains/availability 60 a minute, for your account
platform_domains.claim POST /client/platform-domains/claims 6 an hour, for your account
crypto.deposit_check POST /billing/crypto/check 12 a minute, for your account
storefront.free_order POST /services/order for a plan that costs nothing 12 in 10 minutes, for your account
user.mfa_verify POST /auth/mfa/verify, /auth/mfa/enable, /auth/mfa/disable and /auth/mfa/recovery-codes together 10 in 5 minutes, for your account
apps.create POST /client/apps, and POST /orgs/{org_slug}/apps for an organization 20 an hour, for the account or organization that will own the app
apps.write Every request that changes an app under /client/apps/ or /orgs/{org_slug}/apps/: creating, changing or deleting it, its variables, domains, deployments and webhook secret 120 an hour, for each person or API key
apps.deploy POST .../{app_uuid}/deployments, POST .../{app_uuid}/redeploy and a rollback 30 in 10 minutes, for each app
apps.domain_verify POST .../{app_uuid}/domains/{hostname}/verify 30 in 10 minutes, for each app

The matching routes of an organization's customer portal, under /orgs/{org_slug}/portal/, have the same budgets for each customer. The staff console has budgets of its own on actions such as charges, refunds, credit and exports.

Over a budget, the action answers:

JSON
{
  "detail": {
    "error": "rate_limited",
    "message": "Too many requests for this action. Please wait and try again.",
    "action": "container.power",
    "retry_after_seconds": 60
  }
}

retry_after_seconds and the Retry-After header both give the length of the whole window. Waiting that long always frees the budget.

Apps answers the same way without action, and its message names what ran out, such as Too many deployments of this app. Wait a few minutes.

Organization API keys and the Store API

Section titled Organization API keys and the Store API
Organization API key
Each key has its own limit, set when it is created: 4,000 requests in any 60 minutes by default. Over it, the Commerce API answers 429 with API key rate limit exceeded and Retry-After: 3600. Create organization API keys sets the limit.
Store API payments
Starting a payment and completing a cart each allow 20 tries for one cart in 10 minutes, and 60 from one IP address for one store. Over either, the Store API answers 429 with "error": "rate_limited", the message Too many payment attempts for this cart. Try again in a few minutes. and Retry-After: 600.

SMTP Relay has sending limits of its own, which SMTP Relay sending limits describes.

  • Read Retry-After, a whole number of seconds, and send nothing more to that route until it has passed.
  • When an answer has no Retry-After, wait 1 second, then double the wait after each 429 up to a minute, with a random part added so that many clients do not retry at the same moment.
  • Never retry in a loop without a wait: 8 refusals in a row block your address for 5 minutes.
  • Poll less often, and read a list once instead of one record at a time (Pagination and filtering).
  • When you retry a payment or an order after a 429 or a lost connection, send the same Idempotency-Key, so that it happens only once (Idempotent requests).