Skip to content

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.

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.
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”

  1. Only from POST /auth/token, which answers as OAuth 2 asks (RFC 6749 §5.2): invalid_request for a body that is missing members or cannot be read, invalid_grant for a wrong password, a bad or reused refresh token, or an account that may not sign in, invalid_scope for a scope naming no user scope, and unsupported_grant_type for a grant_type other than password or refresh_token. The body also has the same error member.
  1. No key, or a key or token the site refused. The reason is never given. The answer carries WWW-Authenticate: Bearer (nothing sent) or Bearer error="invalid_token" (something was sent).
  1. 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.
  1. 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.
  1. 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.
  1. The request clashes with the current state:
  • a stored Idempotency-Key answer 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
  1. The resource changed since the If-Match value you sent. GET it again and retry. See Writes.
  1. A query or body value broke a rule. Read errors. For listing searches this includes an unknown category, a query parameter the endpoint does not take (a public key in ?api_key= is the one exception), a limit outside 1 to the site’s maximum, and an unknown locale. For writes it also covers the web form’s own refusals: a missing field, an unknown place, an unknown or expired photo_tokens entry, a wrong current_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 has code: "rejected" on each entry in errors.
  1. 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-After seconds. See rate limits and write limits.
  • Retry 429, 500 and 503 after a wait. 429 and 503 say how long.
  • On 401 token_expired, refresh the token and retry once. Do not retry other 401s unchanged.
  • Do not retry 400, 403, 404, 405 or 422 unchanged.
  • Retry a write after a timeout with the same Idempotency-Key: Writes.
  • Treat an unknown code by its status.
  • Plugin endpoints use the same format. See Plugin endpoints.