Every error is an RFC 9457 problem document with Content-Type: application/problem+json:
{
"type": "https://www.theskillsfest.com/developers/errors/insufficient_data_class",
"title": "Insufficient data class",
"status": 403,
"detail": "This key cannot write background_check. Grant the data:safeguarding scope.",
"instance": "/api/v1/members/external/acme-membership/U-1042",
"request_id": "req_01K3XQ7YB4N2M",
"errors": [{ "field": "background_check", "message": "requires data:safeguarding" }]
}Branch on type, not on the wording of detail. The type URIs are part of the v1 contract and will not change.
unauthorized — 401The key is missing, malformed, revoked, expired, or belongs to a workspace that is no longer active. The response is deliberately identical for all of these, so it cannot be used to work out which keys exist.
api_disabled — 403The key is valid but the API is off for this workspace — either it was never enabled, or an Owner switched it off in Settings → API. Takes effect on the very next request.
ip_not_allowed — 403This key has an IP allowlist and the request did not come from one of them.
insufficient_scope — 403The key lacks a resource scope this endpoint needs. The missing scopes are named in errors[].
insufficient_data_class — 403The request touched a field outside the key’s data classes. The field is named. We refuse rather than accepting the write and dropping that field silently.
workspace_paused — 403The workspace is paused for billing and is read-only. Reads and exports keep working; writes resume when billing does.
addon_required — 403The endpoint needs an add-on this workspace does not have — lodging, today. Separate from scopes: holding lodging:read is not enough on its own.
not_found — 404No such resource in this workspace. A resource that exists in a different workspace also answers 404 — a 403 would confirm it exists.
method_not_allowed — 405The path exists but not with this HTTP method.
conflict — 409The request conflicts with the current state of the resource.
idempotency_in_progress — 409A request with this Idempotency-Key is still running. Wait and retry with the same key.
idempotency_key_reuse — 422This Idempotency-Key was already used for a different request body. We refuse rather than returning the earlier result, which would answer a question you did not ask.
unprocessable_entity — 422The request was understood but cannot be processed: a missing or unknown field, a malformed cursor, or a batch over the limit. Details are in errors[].
payload_too_large — 413The request or the requested export is too big — a CSV over the row cap, for instance. Use the paginated JSON endpoint.
rate_limited — 429Too many requests for this key. Retry-After says how long to wait; the RateLimit-* headers on every response let you slow down before this happens.
internal_error — 500Something went wrong on our side. Quote the request_id if you contact us — it identifies the exact call.