# Error Surface > Audit the error responses a public API actually returns, endpoint by endpoint, then fix them. Paste the responses as > curl -i prints them; the browser checks each one for what an integrator needs to fix the problem alone - one RFC 9457 > problem-details envelope everywhere, a machine-readable code, the field, value and constraint, a retry signal > (Retry-After, retryable), a request ID echoed in the body, the right status, and no leaked internals - picks the > taxonomy, classes every status as retryable or not, lists the endpoints that need an idempotency key and works out a > full-jitter backoff. Metered runs redesign the error catalog with every observed code mapped, and write the > idempotency and retry contract for the same endpoints. Built on the SkillSafe skills @samber/api-error-design and > @samber/api-idempotency-retry, from samber/developer-platform-skills (MIT), by Samuel Berthe. It never invents an > endpoint, a status or a vendor's number. https://error-surface.skillsafe.ai/ ## What is free - Per response: a 200 carrying an error; an HTML page or plain text instead of an envelope; problem details not served as application/problem+json; no machine-readable code; a generic message or an identifier as the message; validation without field-level detail; 401 and 403 swapped; 400 where 422 fits; a 429 or 503 with no Retry-After; a 5xx with no retry signal; retryable set against the status; no request ID or one not echoed; a stack trace, SQL error or internal path in the body. - Across responses: more than one envelope shape; error responses without a code; one code returned with two statuses; state-changing endpoints sent without an Idempotency-Key; a retry chain longer than a 24-hour replay window. - The taxonomy by the skill's ranking: code/subcode by default, flat for a small surface or a near ship date, domain/reason for REST plus gRPC, gRPC only, or a shared taxonomy. - Retry classes: 408, 429, 502, 503, 504 retryable; 500 ambiguous; other 4xx not. POST and PATCH need a key; PUT and DELETE are checked. - A full-jitter backoff schedule (sleep = random(0, min(cap, base x 2^n))) against an overall deadline, and an OpenAPI ProblemDetails component. Exports: the audit (.csv), everything (.json). ## The metered lanes Two tasks on gpt-terra, metered per run, routed by `task`. Input string fields: `task` (catalog or retry), `api`, `responses`, `carry` (retry only: the catalog's codes) and `facts`. - `catalog` replies with `summary`, `taxonomy`, `catalog` (code, subcode, domain, status, title, retryable, user_safe, message, replaces), `examples` (RFC 9457 payloads), `stability`, `rollout` and `caveats`. - `retry` replies with `summary`, `unsafe`, `verify`, `key`, `conflicts` (mismatch and in-flight), `ttl`, `claim`, `failures`, `client` (retry_on, never_retry, jitter and the backoff numbers), `docs` and `caveats`. The page holds every reply to its own facts: the taxonomy it chose, every observed code mapped, one status per code, retryable following the status, payloads that agree with their entry; exactly the retry-unsafe endpoints, your backoff numbers, a replay window above the floor, two distinct conflict codes, retries on the allowlist only, and never exactly-once. ## Links - API tutorial: https://error-surface.skillsafe.ai/api.html - Source skills: https://skillsafe.ai/skill/@samber/api-error-design and https://skillsafe.ai/skill/@samber/api-idempotency-retry