Errors
Every error response is RFC 7807 Problem Details
(application/problem+json). The shape is predictable,
extensions are additive, and instance carries a
/requests/{id} correlation pointer that matches the
x-request-id response header and the request id shown in
the dashboard audit viewer.
Typical 401 body
{
"type": "https://skadispecialty.com/api/problems/invalid-signature",
"title": "Invalid signature",
"status": 401,
"detail": "Signature verification failed",
"instance": "/requests/8f9c2d0a-5b34-4b1d-9c9e-41a2a5b19f3d"
} Problem-type catalog
| Suffix | Status | Common cause |
|---|---|---|
missing-credentials | 401 | Neither Authorization: Bearer nor X-API-Key present. |
invalid-credentials | 401 | API key not found, revoked, or inactive. |
invalid-signature | 401 | HMAC signature mismatch. Double-check ts, body, secret encoding. |
timestamp-skew | 401 | X-Timestamp outside ±5 min of server clock. |
insufficient-scope | 403 | Key lacks the scope this endpoint requires. extensions.required_scope is set. |
expired-credentials | 401 | API key expired or token past exp. |
idempotency-conflict | 409 | Idempotency-Key reused with a different body (in-flight or 24h window). |
rate-limit-exceeded | 429 | Per-IP or per-key rate limit hit. Retry-After is set. |
validation-failed | 400 | Request body failed schema validation. |
not-found | 404 | Referenced resource (policy, quote) not found. |
method-not-allowed | 405 | Wrong HTTP method for this endpoint. |
gone | 410 | Endpoint or transaction kind retired. extensions.redirect_endpoint points to its replacement. |
stale-snapshot | 409 | Quote-then-bind: policy state drifted between draft creation and bind. extensions.fresh_draft is the new draft to bind. |
draft-expired | 410 | Quote-then-bind draft TTL elapsed (24h endorsement/cancellation/audit/extension/oos, 7d renewal/rewrite). Create a new draft. |
internal-error | 500 | Server-side failure. Include x-request-id when reporting. |
Correlation IDs
Send X-Request-Id: <uuid> to carry your own correlation id
through. If omitted, the server generates one. Either way, it is echoed in
x-request-id and in instance, and persisted
alongside the audit row.
Debug flow
- Copy
x-request-idfrom the failing response. - Check Dashboard → Audit — the row should be visible within 2 s.
- If status is 401, verify body + ts + secret in the signature playground.
- If still stuck, escalate with the request-id.