Errors
The status codes and error bodies the Coritan API returns, the fields to read in each, and what to do about them.
A request that fails answers with a status code of 400 or more and a JSON body. Read the status code first: it says what kind of failure it is. The body's detail field then says what went wrong, in one of the three shapes below.
The error body
Section titled The error bodyA sentence
Section titled A sentenceMost errors carry one sentence, written to be shown to a person:
{"detail": "Invoice not found"}
Branch on the status code, not on the words.
An object with a code
Section titled An object with a codeErrors that a program is expected to act on carry an object. error is a code to branch on, message is the sentence to show, and some codes add fields of their own:
{
"detail": {
"error": "rate_limited",
"message": "Too many requests for this action. Try again later.",
"action": "container.power",
"retry_after_seconds": 60
}
}
A few errors name the code reason instead of error, such as a locked server:
{"detail": {"reason": "server_locked", "message": "We have locked this server because activity on it broke our acceptable use policy, and our team is reviewing it. ..."}}
The errors about your account plan name the code code. A request that would take the account past a limit of its plan answers 402 with entitlement_exceeded. entitlement names the limit, limit is its value and used is what the account has. upgrade.plan is the smallest plan that allows one more, and upgrade.addon the add-on that raises the limit; either is null when there is none (When you reach a limit):
{
"detail": {
"code": "entitlement_exceeded",
"entitlement": "websites_max",
"limit": 3,
"used": 3,
"upgrade": {"plan": "plan-pro", "addon": "addon-websites-pack"},
"message": "Your Free plan includes 3 websites, and this account has 3. To add more, upgrade to Pro or buy an add-on."
}
}
On a free server that a brand sells, a feature the free plan leaves out answers 403 with the feature and upgrade_required. coritan.com sells no free server, so a server you order here never answers this (How free servers work):
{
"detail": {
"feature": "backups",
"reason": "free_plan",
"message": "Backups are not included on the free plan. Upgrade to a paid plan, or download your world from the file manager.",
"upgrade_required": true
}
}
Some orders that fail a check of their settings answer 422 with a list of sentences: {"detail": {"errors": ["..."]}}.
A list of field errors
Section titled A list of field errorsA body, query or path value that is missing or has the wrong type answers 422 with one entry for each field. loc says where the field is, and msg what is wrong with it:
{
"detail": [
{
"type": "missing",
"loc": ["body", "password"],
"msg": "Field required",
"input": {"email": "alex@example.com"}
}
]
}
Status codes
Section titled Status codes| Status | Meaning | What to do |
|---|---|---|
400 |
The request is well formed, but it cannot be carried out as sent. detail says why. |
Change the request. |
401 |
The credential is missing, expired, or the wrong kind for the route. | Refresh the token or sign in again, as Authentication describes. |
402 |
A payment did not complete, such as a card the bank declined, or the request would take the account past a limit of its plan (entitlement_exceeded). |
For a payment, read detail, then pay with another method. For a limit, remove something first, or raise the limit with the plan or add-on in detail.upgrade. |
403 |
You may not do this: your role or plan does not allow it, the account is suspended, or the record belongs to someone else. A Client API request with no Authorization header also answers 403 Not authenticated. |
Check the credential and what it may do. Do not retry unchanged. |
404 |
The path or the record does not exist, or it belongs to another account. | Check the ID and the path. |
409 |
The request conflicts with the record's state: a name is taken, the same action is already running, or the record is being deleted. | Read the record again, then decide. |
413 |
A file or a body is larger than the route accepts. detail gives the limit. |
Send less. |
422 |
A field is missing or not valid. | Fix the fields detail names. |
423 |
The server is locked, and detail.reason is server_locked. The lock does not delete your files. |
Reply to the support ticket that came with the lock. |
429 |
Too many requests. | Wait as long as Retry-After says. Rate limits lists the limits. |
500 |
Something failed on Coritan's side. detail is Internal server error. |
Retry later. If it keeps failing, contact support with the time and the request. |
502 |
A system the API depends on refused or failed, such as a payment provider or a domain registrar. detail says which. |
Retry later. |
503 |
The API or one of its services is not available right now. | Retry after the Retry-After header, or later when there is none. |
A 503 while the API starts up has its own body, and asks you to wait two seconds with Retry-After: 2:
{"detail": "Service unavailable: database not ready", "status": "not_ready"}
A 503 while the service is busy, or while too many requests to the same route are still being answered (Rate limits), answers with the body below and also asks you to wait two seconds with Retry-After: 2. Repeat the request after that wait. A request that changes something may have run before the failure, so read the record again before you repeat it, or use an idempotency key on the routes that take one:
{"detail": "The service is busy. Try again in a moment."}
Error codes
Section titled Error codesThese codes in detail.error, detail.reason or detail.code come up on many routes. The page for each product lists the ones it adds.
| Code | Status | Meaning |
|---|---|---|
entitlement_exceeded |
402 |
The request would take the account past a limit of its plan, such as its websites, load balancers or team members. detail.upgrade names what raises the limit. |
plans_not_open |
403 |
Account plans are not open on your account yet, so you cannot order, change or try one (Plans open in stages). |
turnstile_failed |
403 |
The verification check is on, and turnstile_token is missing or did not pass. |
mfa_required |
401 |
A pending token from a sign-in with two-factor authentication was sent to a route that needs a full sign-in. |
reauth_required |
403 |
An Organization API action needs a step-up in the last 10 minutes. max_age_seconds says how long one lasts. |
rate_limited |
429 |
An action's own budget is spent. action names it, and retry_after_seconds gives the length of its window. |
free_limit_reached |
409 |
You already have the most of that free plan an account may hold. Remove one, or choose a paid plan. |
free_tier_paused |
503 |
Free servers are at capacity, so a storefront takes no orders for them right now. |
plan_not_sold_here |
403 |
The plan cannot be ordered through this API. |
server_locked |
423 |
The server is locked while Coritan reviews it. |
server_deleting |
409 |
The server is being deleted, so it takes no more actions. |
The Commerce API and the Store API answer every error with an object like this, with codes such as not_found, invalid, conflict, forbidden, commerce_not_enabled, scope_required and idempotency_key_reused. Authentication lists the codes about credentials, and Idempotent requests the codes about repeated requests.
Errors from in front of the API
Section titled Errors from in front of the APIThe proxy in front of the API can refuse a request before the API sees it. Its answers carry error at the top level and no detail:
| Status | Body | Meaning |
|---|---|---|
429 |
{"error":"Too many requests"} |
Your address sent too many requests or opened too many connections. Retry-After is 1. |
413 |
{"error":"Request body too large"} |
The body is larger than the proxy accepts. |
Handle both bodies: read detail when it is there, and error when it is not.