Content-Type: application/problem+json:
type URI — it is stable across releases and
dereferenceable to documentation. title and detail are
human-readable and may be reworded; do not switch on them.
Some problem types carry extension members (the quota block
above is one). The base members (type, title, status, detail,
instance) are always present; extensions are documented per error
type below.
Authentication & access
| Status | Type URI | When |
|---|---|---|
| 401 | https://errors.attestly.io/authentication-failed | Missing, malformed, or revoked API key. |
| 402 | https://errors.attestly.io/subscription-inactive | Subscription is no longer active. |
| 429 | https://errors.attestly.io/quota-exceeded | Monthly cap reached for the current billing period. |
| 429 | https://errors.attestly.io/rate-limit-exceeded | Too many requests in a short window. |
Retry-After and X-RateLimit-* headers. The
quota-exceeded type additionally carries a quota extension with
limit, used, period_started_at, period_ends_at. See
Quotas.
Validation
| Status | Type URI | When |
|---|---|---|
| 422 | https://errors.attestly.io/request-validation-failed | Bad JSON, wrong types, missing required fields. |
| 422 | https://errors.attestly.io/program-validation-failed | Ruleset structure invalid (depth, refs, ceilings). |
| 422 | https://errors.attestly.io/program-compilation-failed | Ruleset references could not be compiled. |
| 422 | https://errors.attestly.io/unknown-source | Ruleset references a source you can’t access. |
Catalog
| Status | Type URI | When |
|---|---|---|
| 404 | https://errors.attestly.io/ruleset-not-found | ruleset_id doesn’t resolve. |
| 409 | https://errors.attestly.io/ruleset-already-exists | (name, version) already taken. |
Idempotency
| Status | Type URI | When |
|---|---|---|
| 422 | https://errors.attestly.io/idempotency-key-invalid | Malformed Idempotency-Key header. |
| 422 | https://errors.attestly.io/idempotency-key-conflict | Same key, different request body. |
| 429 | https://errors.attestly.io/idempotency-key-exhausted | Too many concurrent requests with the same key. |
| 410 | https://errors.attestly.io/idempotency-replay-expired | Replay window for that key has elapsed. |
Server (5xx)
| Status | Type URI | When |
|---|---|---|
| 500 | https://errors.attestly.io/internal-error | Unexpected server error. |
| 503 | https://errors.attestly.io/database-unavailable | Transient infrastructure issue. |
support@attestly.io.
Partial failures (200)
A source or check failure does not fail the whole request. The response is200 but verdict.status = "degraded" and the affected
check carries status: "failed" with an error message. See
Verdicts.