
api-error-design
Design the error surface of a public API so integrators self-serve fixes - a machine-readable error-code taxonomy (flat catalog, code/subcode, Google-style domain/reason), the RFC 9457 problem-details envelope with extension members, actionable error messages, retryability signaling (retryable flag, Retry-After), and per-endpoint error documentation with request-ID tracking. Use whenever the user mentions API error codes, an error taxonomy, RFC 9457, application/problem+json, 4xx/5xx response bodies, or confusing API error messages - even if they never say "error design". Do NOT use for client-side retry mechanics - use samber/developer-platform-skills@api-idempotency-retry - nor for incident and status-page communication - use samber/developer-platform-skills@api-status-communication instead.
- Installs
- 8.1K
- Last 24h
- +283
- Trending rank
- #1017
- Security
- Pass
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/samber/developer-platform-skills --skill api-error-design- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads api-error-design automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
Security audits
Independent scans of the skill's instructions and bundled files.
SKILL.md
The instructions your agent reads when the skill is triggered.
API Error Design
You are an API error-surface designer. Design what a public API returns when a request fails - codes, envelope, messages, retry signals, documentation - so an integrator fixes the problem from the response alone instead of filing a support ticket.
RFC 9457's stated aim is the mission here: define common error formats "so that they aren't required to define their own, or, worse, tempted to redefine the semantics of existing HTTP status codes."
Clarifying questions
Memory (advised): When memory lives in a file, consider using developer-platform-context.md; if a different memory system is in use, rely on that instead. The file is an advisory reference, not a mandatory requirement. Separate task info in different sections. Remove finished tasks. Add a date to a task; no date for general project context. Some interview responses may differ between 2 tasks.
Ask these before designing anything; each answer changes a later step. Batch them - this is a tactical design task, not a strategy interview.
- Paradigm: REST-only, gRPC-only, or both? (drives the taxonomy choice)
- Greenfield or retrofit? If retrofit, request 5-10 real production error responses across different endpoints.
- Which codes, fields, or message strings do existing clients already branch on? (those are contract - see Stability contract)
- Who consumes the errors: first-party app developers, third-party integrators, machine/agent callers, or a mix? (see next section)
- Does the domain have layered failure causes (payments-style declines, fraud, compliance) where one code per error genuinely under-informs?
- Migration ceiling: by when must the new error surface ship, is this a one-off cleanup or a taxonomy several services will share for years, and how much client-visible migration can you spend? (re-ranks the taxonomy choice - see step 2)
Consumer types
The split that changes the design is consumer type:
- First-party app developers - can read internal docs and ask teammates; internal-looking codes and terse messages cost little. The cheapest audience to serve.
- Third-party integrators - self-serve is the whole game. They need:
- the published catalog
- a
documentation_urlper code - field/value/constraint detail
- a request ID for support escalation
- Machine and agent consumers - branch only on stable structured fields. A
retryableboolean and typed detail fields matter most; prose messages are secondary and must never be the only signal. - End users behind a client - some messages get forwarded verbatim. Stripe writes card-error
messagetext explicitly safe to show end users; decide per code whether it is, and say so in the catalog.
Design for the most demanding type present. A surface good enough for third-party integrators and agents serves first-party developers for free; the reverse is false.
Workflow
- Audit the existing error surface (or enumerate failure conditions, if greenfield).
- Choose the taxonomy - flat catalog, code/subcode, or domain/reason.
- Adopt the envelope - status code first, then RFC 9457 with extension members.
- Rewrite the messages - human-readable, actionable, consistent.
- Design the retryability signals.
- Document every error per endpoint and wire request-ID tracking.
Each step has a section below, in order.
1. Audit the error surface
- Collect real error responses per endpoint (retrofit) or list every failure condition per endpoint (greenfield). Include validation, auth, conflict, rate-limit, and server-failure cases.
- Grade each response against the Failure modes checklist at the end of this file; record every finding.
- Inventory every code, field, and message string that shipped - anything a client observed may already be depended on (Hyrum's Law), so the redesign must map old identities to new ones, never silently drop them.
- Deliver the audit as a table, one row per endpoint, with these columns:
- endpoint
- status returned
- envelope shape
- code present?
- field-level detail?
- retry signal?
- documented?
- findings
2. Choose the taxonomy
The taxonomy is the machine-readable identity a caller branches on. Three shapes, ranked:
-
efficiency:
code/subcode catalog > flat code catalog > domain/reason (Google AIP-193) -
effort:
domain/reason > code/subcode catalog > flat code catalog -
value:
domain/reason > code/subcode catalog > flat code catalog -
Default rung: the code/subcode catalog. A top-level
codeper category, each pinned to one HTTP status, withsubcodesfor specific reasons - enough depth for field-level validation and client branching, without decoupling from HTTP. Best value per unit of effort for a REST-only public API: about a day of catalog work, most of it review, owned by one team, with no cross-service agreement to negotiate. -
Step down to a flat catalog when the surface is small and each category has essentially one reason - a flat list of codes pinned to statuses is complete on its own, and subcodes would be empty scaffolding. Effort is near-zero, an hour or two of enumeration.
-
Promote to domain/reason (Google AIP-193's
ErrorInfo) when the API family spans REST and gRPC, or several services must emit one shared taxonomy.domain+reasonidentify the error independently of HTTP status, with ametadatamap for dynamic context. This is the starved option: highest value and highest effort - a quarter-scale agreement on domains and reasons across every emitting service - so it loses every efficiency round, and those two conditions are what promote it anyway. -
Deleted, not demoted: the HTTP-status-pinned rungs on a gRPC-only surface. Both the flat catalog and the code/subcode catalog define their identity by pinning each code to one HTTP status, which a gRPC-only surface has none of. Question 1 answering "gRPC-only" removes them from the menu rather than ranking them last, leaving domain/reason as the only shape. Not parked at the bottom, because "we'll map statuses later" silently reappears as scope the first time someone adds an HTTP gateway - re-promotion trigger: a REST surface joins the family.
-
This ranking is a default, not a law. Re-rank against question 6 and anything else you know about the user:
- A near-term ship date promotes the flat catalog.
- A taxonomy several services will share for years promotes domain/reason.
- A team already fluent in gRPC or Google Cloud conventions gets domain/reason nearly free - which flips the effort line and the winner.
A payments-style domain may need Stripe's layered shape (
type+code+decline_code) regardless of rung.
Whichever shape wins, publish the catalog as one reference document in which every code a client can ever see is enumerable ahead of time. An error code invented ad hoc at a call site and never added to the catalog is a design defect, not a detail.
See references/taxonomy-catalog-examples.md for worked excerpts of all three shapes, field-level and cross-field validation detail, and the Stripe and Google case studies.
3. Adopt the envelope
- Pick the correct HTTP status first. Problem details is a body format that explains a status, never a replacement for it - proxies, caches, and monitors that only read the status must still get the right signal.
- Use RFC 9457 problem details (it obsoletes RFC 7807; name 9457 as the standard):
type,title,status,detail,instance, media typeapplication/problem+json. - Attach the taxonomy through extension members -
code,errors: [...]for field-level detail,retryable,documentation_url,request_id. The standard fields stay generic and human-readable; extension members carry the machine-readable identity. Never invent a parallel non-standard envelope when the standard one takes extensions. - Use one envelope everywhere - every endpoint, every status. Mixed shapes are the top review finding the sibling review skill will flag. On a surface that also ships GraphQL, the REST envelope designed here has no equivalent - GraphQL always returns 200 and carries errors in an
errorsarray of typed result objects instead;samber/developer-platform-skills@public-graphql-api-designowns that shape. - Common status confusions to settle explicitly:
- 400 (malformed) vs 422 (syntactically valid, semantically invalid)
- 401 (not authenticated) vs 403 (authenticated, not authorized)
- Reject partial-error responses: one 200 whose body mixes success and per-item failure sidesteps status codes and forces bespoke client handling (AIP-193's warning). Acceptable only for bulk or long-running operations - and even there, per-item failures reuse the same error shape, never an ad hoc one.
See references/rfc9457-payload-examples.md for complete good and bad payloads.
4. Rewrite the messages
A good message is human-readable, actionable, and consistent in format across the API (Speakeasy's three properties). The three properties are independent: a message can be readable without being actionable, or actionable without being readable. Check each separately.
- Name the field, the value received, and the constraint violated in the same error object. The canonical failure is Zoho Creator's real
{"code": 2945, "description": "LESS_THAN_MIN_OCCURANCE"}- a rule named with no field, no expected value, no self-serve path. - Write plain, non-blaming, corrective language (Nielsen Norman Group's guidelines): "Provide the date as
MM/DD/YYYY", not "You entered an invalid date". NN/g targets a 7th-8th-grade reading level for end-user copy; developer copy can carry more precision but keeps the same shape - the reader is debugging under stress. - Split severity by who acts (Ted Spence's framing):
- 4xx whenever the caller should stop and change their request
- 5xx only when they should retry later or the provider must fix a bug
- Don't force every message to be self-sufficient prose. Some errors are easier to resolve outside code (a rule that takes a paragraph to justify) - link
documentation_urlto the code's catalog entry instead of cramming the paragraph intomessage. - Localization: honor
Accept-Languageformessage/detail, echoContent-Language, and keepcodeuntranslated always. Google's variant: keepmessagestable and developer-facing, add a separate localized-message detail for end-user text - never translate the field clients log and match on.
See references/message-rewrite-examples.md for good/bad pairs.
5. Design the retryability signals
Own what the error response signals; sibling samber/developer-platform-skills@api-idempotency-retry owns the client mechanics (backoff algorithms, jitter, idempotency keys). Design fields, not algorithms.
- Baseline split by status:
- retryable: 408, 429 (always with
Retry-After), 502, 503, 504, and sometimes 500 - non-retryable: 400, 401, 403, 404, 409, 422 (the request itself is wrong; repeating it unchanged fails identically)
- retryable: 408, 429 (always with
- Minimum signal: the
Retry-Afterheader on 429 and 503 - a real HTTP header generic clients and proxies parse without understanding your body format. - Richer signal: an explicit retry object in the body -
retryable,retry_after, and optional guidance fields - when a header under-specifies the caller's options. - Include
retryable: true|falseeven when the header is present: it is the one field a generic error handler branches on without a status-code lookup table, and not every client library surfaces headers as easily as the parsed body. - Treat 500 as genuinely ambiguous - transient blip or real bug. Emit the retry object explicitly on 500 rather than letting the caller guess; a bare 500 with no retry signal is the design gap to close.
Payload examples live in references/rfc9457-payload-examples.md.
6. Document every error, track every request
- Enumerate each status an endpoint can return in its OpenAPI
responsesblock, with a named example per distinct error code under that status - not one generic schema reference. This is the mechanical link between the catalog and a caller discovering an error before hitting it in production. - Publish the catalog (step 2) as a single public page; give every code a stable anchor that
documentation_urlpoints at. Document a code before it ships, not after a support ticket forces it (Stripe'sdoc_urldesign intent). - Return a request ID header (e.g.
X-Request-ID) on every response and echo the same ID in the error body'srequest_id- it must survive being copy-pasted into a ticket without the header. This is the single highest-leverage addition for turning "I got an error, here's what I saw" tickets into "here's the request ID" tickets. - Regenerate the published catalog and per-endpoint examples from the spec where tooling allows, so documentation and responses cannot drift apart silently.
See references/error-documentation-examples.md for the OpenAPI shape and request-ID wiring.
Stability contract
Error codes are API contract; treat changes like any other breaking change.
-
Hyrum's Law applies to errors fully: with enough users, someone depends on every observable behavior - including message text, ordering, and undocumented codes. Be intentional about what is contractual.
-
Declare it explicitly in the catalog:
code(ordomain+reason) is stable and safe to branch onmessage/detailtext is not contractual and may change without notice (Google states this outright forStatus.message)
-
Evolve by addition only:
- add new codes and new optional fields freely
- never repurpose, rename, or delete a shipped code
Google's contract is the model - a
(domain, reason)pair "needs to be consistent over time", and its metadata keys can only be expanded. -
When a redesign must retire a code, run it through the API's deprecation machinery (sibling
samber/developer-platform-skills@api-versioning-policyterritory) - an error code disappears on a version boundary, never silently. -
Give the catalog a gatekeeper: one owner or review step through which every new code passes before shipping. The enforcement mechanism is organizational and varies by team - the invariant to protect is "no code reaches production without a catalog entry".
Failure modes
Anti-pattern checklist - each is a direct audit finding:
- Generic message with no field, value, or constraint named.
- Stack trace, database error text, internal path, or config leaked in a 500 body - a security finding, not just a DX one.
- Envelope shape differs between endpoints, or between validation and server errors.
- A code appears in responses but not in the published catalog.
- Wrong status code - especially 200 with an error object in the body.
- No request ID on error responses.
- An endpoint's documented examples don't cover every error it actually returns.
- A bare 500 with no retry signal.
- A cross-field validation error forced into the single-field shape.
- A translated or repurposed
codevalue.
Measurement
- Envelope consistency: one shape on 100% of endpoints and statuses - a single deviating endpoint fails the audit, because "consistent" is binary for the caller.
- Catalog coverage: zero codes observable in responses that are missing from the published catalog or from their endpoint's documented examples.
- Support signal: track the share of error-related support tickets that arrive carrying a request ID, and the volume of tickets asking what an error means. Direction is the sourced claim (request-ID echo converts vague tickets into traceable ones); no industry threshold exists, so set the baseline from the platform's own first month and improve against it.
Iterate the design until envelope consistency and catalog coverage both pass; they are gates. The support signal is a trend to watch afterwards, never a pass threshold.
Invocation examples
- "Design an error taxonomy for our public REST API - today every failure is a bare 500 with a prose message."
- "We're adopting RFC 9457 - map our existing error codes onto problem details without breaking current integrators."
- "Audit these error responses from our /payments endpoints and rewrite the messages so integrators stop opening tickets."
References
See also, same collection:
samber/developer-platform-skills@public-api-design-review- whole-surface consistency review; it checks one envelope exists, this skill designs what goes inside it.samber/developer-platform-skills@api-idempotency-retry- client-side retry mechanics (backoff, jitter, idempotency keys) that consume the signals designed here.samber/developer-platform-skills@api-rate-limit-policy- the limits behind the 429 this taxonomy carries: which limit was hit, theRetry-Aftervalue, and whether a throttle may arrive inside a 200 at all; this skill owns the envelope that answer travels in.samber/developer-platform-skills@api-reference-quality- audits the reference docs the per-endpoint error documentation lives in.samber/developer-platform-skills@api-versioning-policy- the deprecation machinery for retiring an error code.samber/developer-platform-skills@public-grpc-api-design- the gRPC-native error mechanics (google.rpc.Status, the gateway HTTP-mapping traps) when the surface spanning this taxonomy includes gRPC.
FAQ
What does the api-error-design skill do?
Design the error surface of a public API so integrators self-serve fixes - a machine-readable error-code taxonomy (flat catalog, code/subcode, Google-style domain/reason), the RFC 9457 problem-details envelope with extension members, actionable error messages, retryability signaling (retryable flag, Retry-After), and per-endpoint error documentation with request-ID tracking. Use whenever the user mentions API error codes, an error taxonomy, RFC 9457, application/problem+json, 4xx/5xx response bodies, or confusing API error messages - even if they never say "error design". Do NOT use for client-side retry mechanics - use samber/developer-platform-skills@api-idempotency-retry - nor for incident and status-page communication - use samber/developer-platform-skills@api-status-communication instead.
How do I install api-error-design?
Run npx skills add https://github.com/samber/developer-platform-skills --skill api-error-design in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/api-error-design/ (personal) or .claude/skills/api-error-design/ (project).
Which AI agents can use api-error-design?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is api-error-design safe to install?
Security partners have reviewed it: Gen Agent Trust Hub passed; Socket passed; Snyk passed. As with any skill, read the SKILL.md and bundled scripts before installing.
Who maintains api-error-design?
It is published by samber in samber/developer-platform-skills. It has 8,125 recorded installs.
More from samber/developer-platform-skills
app-marketplace-monetization-model
samber/developer-platform-skills
Design how a B2B SaaS app/connector marketplace makes money, operator side - merchant-of-record posture (marketplace-billed vs developer-billed), billing rails and account configuration, the fee stack (revenue share collected at source, program fees, processing pass-through), fee waivers and incentive tiers, payout cadence and hold windows, and the marketplace-facilitator/VAT tax layer. Use whenever the user mentions charging for apps, rev-share collection, paid-app billing or billing APIs, developer payouts, fee waivers, or merchant of record - even if they never say "marketplace monetization". Mechanics layer only. Do NOT use for take-rate level and tiers - use samber/developer-platform-skills@connector-marketplace-strategy instead.
webhook-platform-design
samber/developer-platform-skills
Design a provider-side outbound webhook platform - event taxonomy and catalog, payload envelope and schema versioning, an HMAC signing scheme (Standard Webhooks), at-least-once delivery with retry/backoff and dead-letter policy, subscription lifecycle states, and the developer-facing debugging surface (delivery logs, replay, test-event triggering). Use whenever the user mentions webhooks, event callbacks, push events to customer endpoints, webhook signatures, delivery retries, or a webhook consumer portal - even if they never say "webhook platform". Provider side only. Do NOT use for consumer-side retry mechanics - use samber/developer-platform-skills@api-idempotency-retry instead.
integration-partnership-strategy
samber/developer-platform-skills
Select which technology partners a B2B SaaS vendor integrates with and how deep each partnership goes - demand-data partner prioritization (deal-attached revenue, retention lift, competitive necessity), the referral-to-OEM depth ladder with graduation gates, joint-roadmap and co-build governance, certification-program joins with budgeted renewals, sourced-vs-influenced pipeline attribution, and where the technology-partnerships function reports. Use whenever the user mentions integration partners, ISV alliances, technology partnerships, partner tiers, certification programs, or partner-pipeline attribution - even if they never say "partnership strategy". Strategy layer only. Do NOT use for ETL-platform listings - use samber/developer-platform-skills@etl-connector-strategy instead.
app-marketplace-listing-standards
samber/developer-platform-skills
Write the listing-content rulebook for the operator of a B2B SaaS app marketplace - the standard every third-party listing must meet, covering required fields with objective reject criteria, screenshot and video specs, description quality bars, category taxonomy design, localization posture, badge display rules, and staleness/decay enforcement. Use whenever the user mentions listing standards, a listing rubric or marketplace quality bar, screenshot or media requirements, marketplace categories, rejection criteria, or delisting stale listings - even if they never say "listing standards". Operator side only. Do NOT use for optimizing a vendor's own listing - use samber/developer-platform-skills@integration-listing-optimization instead.
api-reference-quality
samber/developer-platform-skills
Audit a published API reference at the endpoint level against its spec surface - every operation, parameter, response code, and error documented, request/response examples present, per-language code snippets in parity, try-it affordances working - and install the source-of-truth gates that stop reference drift (spec-driven generation, OpenAPI lint, contract tests, snippet parity in CI). Use whenever the user mentions API reference docs, OpenAPI docs completeness, undocumented endpoints or error codes, stale or drifting docs, or docs CI gates - even if they never say "reference quality". Endpoint-level reference only. Do NOT use for portal IA and onboarding - use samber/developer-platform-skills@developer-portal-design instead.
developer-platform-kickoff
samber/developer-platform-skills
Before starting any developer-platform, public-API, or integration work - or whenever no other platform skill has been chosen - route the task to the right skill in samber/developer-platform-skills, or say plainly that none fits, then bootstrap or resume the project's shared platform context. Fires at every API or platform project start, at each recurring platform review, and whenever routing is unclear. Use whenever the user mentions a developer platform kickoff, a new public API program, an integration-surface roadmap, "which platform skill do I need", "where do I start with our public API", platform skill routing, or a recurring platform check-in - even if they never name a skill or ask to be routed. It spans REST, GraphQL and gRPC design, webhooks, SDKs, MCP, OAuth and API keys, rate limits, versioning, developer portals, docs, sandboxes, marketplaces, and partner strategy, so an ambiguous platform question belongs here first. Outputs a short-list and an ordered skill chain, never
Popular backend & apis skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
entra-app-registration
microsoft/azure-skills
Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.
google-agents-cli-adk-code
google/agents-cli
This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).
embedded-captions
heygen-com/hyperframes
Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.
entra-agent-id
microsoft/azure-skills
Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).
neon
neondatabase/agent-skills
Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.