API errors
Every error is JSON with Content-Type: application/problem+json
(RFC 9457). Branch on the HTTP status for the
class of error and on code for the exact case.
{ "type": "https://mindstellar.com/docs/developers/api/errors/#not_found", "title": "Not found.", "status": 404, "detail": "No such listing.", "code": "not_found", "instance": "urn:request:Xq3v9LmT2aBc"}| Member | Meaning |
|---|---|
type |
A link to the code’s entry on this page. |
title |
The same text for every case of a code. |
status |
The HTTP status, repeated. |
detail |
What went wrong this time, for people. It may be in the site’s language. Do not parse it. |
code |
The stable machine name. Match on this. |
instance |
urn:request:<id>: the same id as the Request-Id response header. Quote it when you report a problem. |
errors |
On 422 only: one entry per bad field. |
error |
At POST /auth/token only: the OAuth 2 error, the same as code. |
Codes do not change inside v1. detail wording and language may: branch on code, never on
detail. Plugin endpoints may answer their own codes, named ext_<slug>_<name>.
Every response carries a Request-Id header. Send your own Request-Id or X-Request-Id (8 to 64 characters from A-Za-z0-9._-) and it is echoed back.
Validation errors
Section titled “Validation errors”A 422 validation_failed lists every problem at once in errors:
{ "type": "https://mindstellar.com/docs/developers/api/errors/#validation_failed", "title": "The request is not valid.", "status": 422, "detail": "limit must be at least 1.", "code": "validation_failed", "errors": [ { "pointer": "/limit", "code": "minimum", "message": "must be at least 1", "in": "query" } ], "instance": "urn:request:Xq3v9LmT2aBc"}| Member | Meaning |
|---|---|
pointer |
The field, as a JSON Pointer: /limit, or /price/amount for a nested body field. Empty means the whole input. |
code |
One of the field codes below. |
message |
What is wrong with it. |
in |
query or body: where the field was. Always present. |
Field codes
Section titled “Field codes”| Code | Meaning |
|---|---|
type |
The value has the wrong JSON type. |
enum |
The value is not one of the allowed values. |
minimum |
The number is too small. |
maximum |
The number is too large. |
minLength |
The text is too short or blank. |
maxLength |
The text is too long. |
pattern |
The text does not have the expected form. |
format |
The value is not a valid date, e-mail, URL or id. |
minItems |
The list has too few items. |
maxItems |
The list has too many items, or an account holds as many as it may. |
minProperties |
The object needs at least one member. |
required |
A required field is missing. |
additionalProperties |
The field is not one the endpoint takes. |
invalid |
The value is not accepted, for a reason message gives. |
unknown |
The value names something that does not exist, such as a category, country or custom field. |
taken |
Another resource already uses the value. |
mismatch |
The value does not match, such as a wrong current password, or a region outside the country or a city outside the region. |
limit |
A limit is reached, such as the photos a listing may hold. |
rejected |
The web form refused the input; message is its text. |
Plugin endpoints may add ext_<slug>_<name> codes. Treat an unknown code as invalid.
Each code’s type link points at its anchor here.
| Code | Status | Meaning |
|---|---|---|
invalid_json |
400 | The body is not valid JSON, or not a JSON object. |
invalid_cursor |
400 | The cursor is forged, over a week old, or made for other filters, sort or order. Start again and follow links.next. |
invalid_header |
400 | A malformed header: an Idempotency-Key that is empty, over 255 characters, or not plain visible ASCII. |
banned |
403 | A ban rule matches the account, its e-mail or the address. Covers every call with a user’s token, key or session, sign-up, and posting. |
feature_disabled |
403 | The site has user accounts, API sign-up, personal keys or comments switched off. |
forbidden |
403 | Any other refusal: making or rotating a key with a known scope the admin key lacks, rotating another admin’s key, or an account that cannot save alerts. |
insufficient_scope |
403 | The key lacks the endpoint’s scope. WWW-Authenticate names it: Bearer error="insufficient_scope", scope="admin:users". |
not_owner |
403 | The resource is real and live but belongs to someone else, such as another user’s listing or comment. |
cross_origin |
403 | A page-token call that did not come from the site’s own pages: another Origin, a Sec-Fetch-Site other than same-origin, or neither. |
api_disabled |
403 | The site owner switched the API off. |
not_found |
404 | No such endpoint, API version or record. Also a pending, disabled or spam listing, a disabled user, an unapproved comment that is not the caller’s, and a photo, key or saved search that is not the caller’s. |
method_not_allowed |
405 | The path exists but not for this method. Allow lists the methods that work. |
idempotency_in_flight |
409 | A request with the same Idempotency-Key is still running. Retry-After: 1. |
too_large |
413 | The body is over 1 MB, or a photo is over the site’s largest photo size or 16 MB. |
unsupported_media_type |
415 | The body is not application/json (or application/merge-patch+json on PATCH). A photo is multipart/form-data in a field named photo, or the image itself. |
idempotency_key_reused |
422 | The same Idempotency-Key was sent with a different request. |
listing_limit |
422 | The user has reached the site’s listing limit. detail says what it is. |
login_blocked |
429 | Too many wrong passwords for this account or address, at POST /auth/token, POST /account/password or POST /account/keys. See Retry-After. |
too_many_failures |
429 | Too many wrong keys from this address in 15 minutes. Retry-After: 900. See lockout. |
server_error |
500 | The site hit an error; the cause is in the server’s error log. Retry later. |
maintenance |
503 | The site is in maintenance mode. Retry-After: 900. |
invalid_request, invalid_grant, invalid_scope, unsupported_grant_type
Section titled “invalid_request, invalid_grant, invalid_scope, unsupported_grant_type”- Only from
POST /auth/token, which answers as OAuth 2 asks (RFC 6749 §5.2):invalid_requestfor a body that is missing members or cannot be read,invalid_grantfor a wrong password, a bad or reused refresh token, or an account that may not sign in,invalid_scopefor ascopenaming no user scope, andunsupported_grant_typefor agrant_typeother thanpasswordorrefresh_token. The body also has the sameerrormember.
unauthorized
Section titled “unauthorized”- No key, or a key or token the site refused. The reason is never given. The answer carries
WWW-Authenticate: Bearer(nothing sent) orBearer error="invalid_token"(something was sent).
token_expired
Section titled “token_expired”- An access token was genuine but has run out. Swap the refresh token for a new one and retry
the call. For a page token, reload the page. It is not counted as a failed guess. The answer carries
WWW-Authenticate: Bearer error="invalid_token", error_description="The access token expired". See Authentication.
session_required
Section titled “session_required”- A call with a page token (
X-Shopclass-Token) whose sign-in cookie is missing or not valid, whose page token belongs to another user or an old password, or whose user is suspended or not confirmed. Reload the page. See Same-site session.
wrong_credential
Section titled “wrong_credential”- The endpoint needs another kind of credential: an admin key, a full admin’s key (not a moderator’s), a user’s token or key, an access token (to change the password or sign out), or a same-site session call. Posting or commenting where the site allows only signed-in users also answers this.
conflict
Section titled “conflict”- The request clashes with the current state:
- a stored
Idempotency-Keyanswer that cannot be read - an admin action the state refuses: activating a blocked listing, deleting a currency a listing uses or the site defaults to, revoking a key that is already revoked
precondition_failed
Section titled “precondition_failed”- The resource changed since the
If-Matchvalue you sent.GETit again and retry. See Writes.
validation_failed
Section titled “validation_failed”- A query or body value broke a rule. Read
errors. For listing searches this includes an unknowncategory, a query parameter the endpoint does not take (a public key in?api_key=is the one exception), alimitoutside 1 to the site’s maximum, and an unknownlocale. For writes it also covers the web form’s own refusals: a missing field, an unknown place, an unknown or expiredphoto_tokensentry, a wrongcurrent_password, a language the site does not have, or a key made with an unknown scope (on/scopes/<n>). A write refused by the form hascode: "rejected"on each entry inerrors.
rate_limited
Section titled “rate_limited”- Over a rate limit: the per-minute limits, or an hourly cap on listings, comments, photo
downloads, e-mail changes, saved searches or sign-ups. Wait
Retry-Afterseconds. See rate limits and write limits.
Handling errors
Section titled “Handling errors”- Retry
429,500and503after a wait.429and503say how long. - On
401 token_expired, refresh the token and retry once. Do not retry other401s unchanged. - Do not retry
400,403,404,405or422unchanged. - Retry a write after a timeout with the same
Idempotency-Key: Writes. - Treat an unknown
codeby its status. - Plugin endpoints use the same format. See Plugin endpoints.