Skip to main content
Errors follow RFC 7807 and are served with Content-Type: application/problem+json:
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json

{
  "type":     "https://errors.attestly.io/quota-exceeded",
  "title":    "Quota Exceeded",
  "status":   429,
  "detail":   "Monthly quota of 10000 requests exceeded for this billing period.",
  "instance": "/v1/evaluate",
  "quota": {
    "limit": 10000,
    "used":  10000,
    "period_started_at": "2026-04-15T00:00:00Z",
    "period_ends_at":   "2026-05-15T00:00:00Z"
  }
}
Match against the 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

StatusType URIWhen
401https://errors.attestly.io/authentication-failedMissing, malformed, or revoked API key.
402https://errors.attestly.io/subscription-inactiveSubscription is no longer active.
429https://errors.attestly.io/quota-exceededMonthly cap reached for the current billing period.
429https://errors.attestly.io/rate-limit-exceededToo many requests in a short window.
429 responses carry 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

StatusType URIWhen
422https://errors.attestly.io/request-validation-failedBad JSON, wrong types, missing required fields.
422https://errors.attestly.io/program-validation-failedRuleset structure invalid (depth, refs, ceilings).
422https://errors.attestly.io/program-compilation-failedRuleset references could not be compiled.
422https://errors.attestly.io/unknown-sourceRuleset references a source you can’t access.

Catalog

StatusType URIWhen
404https://errors.attestly.io/ruleset-not-foundruleset_id doesn’t resolve.
409https://errors.attestly.io/ruleset-already-exists(name, version) already taken.

Idempotency

StatusType URIWhen
422https://errors.attestly.io/idempotency-key-invalidMalformed Idempotency-Key header.
422https://errors.attestly.io/idempotency-key-conflictSame key, different request body.
429https://errors.attestly.io/idempotency-key-exhaustedToo many concurrent requests with the same key.
410https://errors.attestly.io/idempotency-replay-expiredReplay window for that key has elapsed.

Server (5xx)

StatusType URIWhen
500https://errors.attestly.io/internal-errorUnexpected server error.
503https://errors.attestly.io/database-unavailableTransient infrastructure issue.
5xx responses are retryable. Use exponential backoff with jitter; if persistent, contact support@attestly.io.

Partial failures (200)

A source or check failure does not fail the whole request. The response is 200 but verdict.status = "degraded" and the affected check carries status: "failed" with an error message. See Verdicts.