api-design
Skill8 starsChanged 9 days agoMITView on GitHub
Designs and reviews HTTP/REST APIs that are consistent, evolvable and safe to retry - resource naming, method semantics, status codes, RFC 9457 errors, pagination, versioning, idempotency keys, ETags, rate limits, long-running operations, webhooks and OpenAPI contracts. Use when creating or changing endpoints, writing an OpenAPI spec, reviewing an API PR, deciding if a change is breaking, or choosing between REST, GraphQL and gRPC.
191 other projects use a version of this.
Adopted by
Most recently taken up by
- RostislavDugin/postgresustheir own version, first seen Nov 8, 2026
- Markssuave/Markssuave-Agent-skillstheir own version, first seen Nov 8, 2026
- Rojios/everything-claude-codetheir own version, first seen Nov 8, 2026
- ishandutta2007/Awesome-Claude-Skillstheir own version, first seen Nov 8, 2026
- databasus/databasustheir own version, first seen Nov 8, 2026
- lhbsaa/apex-unifiedtheir own version, first seen Nov 8, 2026
Used with
Projects with it also use db-design, everything-claude-code and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
yuexueyuSkilldb-design
数据库工程师技能 - Schema设计、索引优化、并发安全、数据库审计。当你涉及数据库表/字段/索引/SQL/迁移/MCP数据库操作、建表改表、写查询时必须使用此技能。即使用户只是说"加个字段"或"查下数据",也应触发。
Also in 4 projects that use this
InfopibeSkilleverything-claude-code
Also in 9 projects that use this
mryeastcodeSkilleverything-claude-code-conventions
Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.
Also in 8 projects that use this
tpavanipradeepSkillnextjs-turbopack
Next.js 16+ and Turbopack — incremental bundling, FS caching, dev speed, and when to use Turbopack vs webpack.
Also in 15 projects that use this
Indium-AI-LabsSkilldata-pipeline-design
Design batch or incremental ETL and ELT pipelines and warehouse models: grain, partitioning, idempotent loads, late-arriving data, data quality tests, PII controls, and cost monitoring, before building them. Use when adding or changing a dbt model, warehouse table, scheduled transformation, or ingestion job. Not for transactional schema design (use the database-design skill) or event-sourced stores (use the event-sourcing-architecture skill).
Also in 3 projects that use this
thejordanleopoldSkillthird-party-integration
Use when integrating with external APIs, payment processors (Stripe), webhooks, or third-party services. Use when implementing API clients with authentication and rate limiting, handling webhooks with signature verification and idempotency, writing contract tests for external services, or isolating third-party dependencies behind adapters. Triggers: \"Stripe\", \"payment integration\", \"webhook\", \"third-party API\", \"external service\", \"API client\", \"integrate with\", \"signature verification\", \"idempotency key\".
Also in 3 projects that use this
Other versions191 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 191
- affaan-m/ECC★ 246ksame name
- databasus/databasus★ 9.3ksame name
- RostislavDugin/postgresus★ 9.3ksame name
- authgear/authgear-server★ 2.1ksame name
- xu-xiang/everything-claude-code-zh★ 1.9ksame name
- Aaronontheweb/dotnet-skills★ 1.2ksame name
- epam/ai-dial-chat★ 501same name
- loulanyue/awesome-claude-notes★ 272same name
- KbWen/agentic-os★ 229same name
- DevelopersGlobal/ai-agent-skills★ 216same name
181 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository60 other files it gives its agents.
- auth-implementationSkill
- background-jobsSkill
- building-agentsSkill
- caching-strategiesSkill
- ci-cd-pipelinesSkill
- cloud-cost-optimizationSkill
- codebase-onboardingSkill
- code-review-changesSkill
- concurrency-patternsSkill
- database-migrationsSkill
- database-schema-designSkill
- database-testingSkill
- data-pipelinesSkill
- data-privacy-retentionSkill
- dependency-upgradesSkill
- design-docsSkill
- design-systemsSkill
- dockerfilesSkill
- domain-driven-designSkill
- event-driven-architectureSkill
- file-storage-uploadsSkill
- frontend-securitySkill
- git-workflowSkill
- graphql-apisSkill
- grpc-servicesSkill
- incident-responseSkill
- infrastructure-as-codeSkill
- internationalizationSkill
- kubernetes-deploymentsSkill
- large-scale-migrationsSkill
- legacy-refactoringSkill
- llm-evalsSkill
- llm-integrationSkill
- mcp-serversSkill
- micro-frontendsSkill
- ml-experimentsSkill
- monorepo-managementSkill
- nosql-designSkill
- observabilitySkill
- orm-patternsSkill
- performance-profilingSkill
- postgres-operationsSkill
- rag-systemsSkill
- react-patternsSkill
- realtime-apisSkill
- resilience-patternsSkill
- root-cause-debuggingSkill
- search-integrationSkill
- security-auditSkill
- seo-and-ssrSkill
- sql-optimizationSkill
- system-designSkill
- test-strategySkill
- threat-modelingSkill
- typescript-patternsSkill
- unit-testingSkill
- verify-before-doneSkill
- web-accessibilitySkill
- web-performanceSkill
- writing-skillsSkill
The file
We split this skill into the rules it gives an agent
9 rules. 0 are common, 8 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 165 edited versions we read keep these.
8
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 18
Not for: internal function signatures.
- Distinctive: line 24
Find the existing conventions first: Read the current OpenAPI spec, two or three existing endpoints, and the error format.
- Distinctive: line 26
Write the contract before the code: Add or update the OpenAPI (3.1+) definition: paths, schemas, required fields, examples, every error …
- Distinctive: line 30
Run the review checklist in references/review-checklist.md before calling it done.
- Distinctive: line 81
Never return 200 with an error payload.
- Distinctive: line 100
Put field-level validation errors in one response, not one error per round trip.
- Distinctive: line 101
Never include secrets, SQL, stack traces or internal hostnames.
- Very specific: line 113
Always cap limit (for example default 20, max 100) and document both.
- Distinctive: line 179
Read references/graphql-and-grpc.md when the API is GraphQL or gRPC, or when choosing between them.
“Common” is measured: kept by at least 6 in 10 of the 165 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
API Design
An API is a contract you cannot take back. Design it so clients can retry safely, evolve without breaking, and understand every failure from the response alone.
When to use
- Adding or changing an endpoint, request/response shape, or error format.
- Writing or reviewing an OpenAPI document or an API pull request.
- Deciding whether a change is breaking and how to ship it.
- Choosing REST vs GraphQL vs gRPC for a new interface.
Not for: internal function signatures.
Pair with schema work: the API and the tables behind it are designed together. Use the database-schema-design skill for the tables if it is installed. If it is not, at minimum give every table a primary key, enforce NOT NULL, UNIQUE and foreign keys in the database, store times as timestamptz (or the database's UTC timestamp type) and money as numeric/decimal, and index every column the API filters or sorts on.
Workflow
- Find the existing conventions first. Read the current OpenAPI spec, two or three existing endpoints, and the error format. Consistency with the existing API beats any rule below; flag conflicts instead of silently diverging.
- Model resources, not actions. List the nouns, their identifiers, and their relationships. Map operations to HTTP methods (table below). Only fall back to an action sub-resource (
POST /orders/{id}/cancel) when the operation is not a state change you can express with PUT/PATCH. - Write the contract before the code. Add or update the OpenAPI (3.1+) definition: paths, schemas, required fields, examples, every error response. Run a linter (for example Spectral) if the repo has one.
- Decide failure behavior explicitly: which status codes, which are retryable, what the problem-details
typeis for each error. - Check compatibility. Compare against the previous spec (for example
oasdiff breaking old.yaml new.yaml) and against the breaking-change rules below. If breaking, stop and agree a versioning or migration plan with the user. - Implement and test the contract: request validation, error mapping, pagination edges (empty, last page), idempotent retries, and conditional requests.
- Run the review checklist in references/review-checklist.md before calling it done.
Resource naming
- Plural nouns, lowercase, hyphenated paths:
/v1/payment-methods/{paymentMethodId}. - Nest only for true ownership and at most one level:
/orders/{id}/items. Otherwise use filters:/items?orderId=.... - IDs are opaque strings in the contract even if they are integers today.
- JSON field names: pick one case (camelCase or snake_case) and never mix. Match the existing API.
- Timestamps: RFC 3339 in UTC (
2026-11-03T14:05:00Z). Durations: ISO 8601 or explicit units in the field name (timeoutSeconds). - Money: integer minor units or a decimal string, always with an ISO 4217 currency code. Never binary floats.
- Enums: strings, documented as extensible; clients must tolerate unknown values.
Method semantics
| Method | Use for | Safe | Idempotent | Typical success |
| GET | Read a resource or collection | Yes | Yes | 200, 304 |
| HEAD | Headers only (existence, ETag) | Yes | Yes | 200, 304 |
| POST | Create in a collection, or non-idempotent action | No | No (make it so with an Idempotency-Key) | 201 + Location, 202, 200 |
| PUT | Full replace at a known URI (or create at client-chosen URI) | No | Yes | 200, 204, 201 |
| PATCH | Partial update | No | Not by default | 200, 204 |
| DELETE | Remove | No | Yes | 204, 202, 200 |
- GET never changes state. No
GET /users/{id}/delete. - PATCH body format must be declared: JSON Merge Patch (RFC 7396,
application/merge-patch+json) for simple cases, JSON Patch (RFC 6902,application/json-patch+json) when you need array operations or test-and-set. - Repeating a DELETE on an already-deleted resource may return 404; that is still idempotent (the server state is the same).
Status codes
| Code | Meaning | Notes |
| 200 OK | Success with body | |
| 201 Created | Resource created | Include Location header and usually the resource |
| 202 Accepted | Work queued, not done | Return a status resource (see long-running operations) |
| 204 No Content | Success, no body | |
| 304 Not Modified | Conditional GET matched | No body |
| 400 Bad Request | Malformed syntax, invalid JSON, wrong types | |
| 401 Unauthorized | Missing or invalid credentials | Send WWW-Authenticate |
| 403 Forbidden | Authenticated but not allowed | Use 404 instead when existence itself is secret |
| 404 Not Found | No such resource (for this caller) | |
| 405 Method Not Allowed | Method not supported on the resource | Send Allow |
| 409 Conflict | State conflict (duplicate, invalid transition) | |
| 412 Precondition Failed | If-Match did not match | Lost-update protection |
| 415 Unsupported Media Type | Wrong Content-Type | |
| 422 Unprocessable Content | Well-formed but fails validation | Pick 400 or 422 for validation and use it everywhere |
| 428 Precondition Required | Server requires If-Match | |
| 429 Too Many Requests | Rate limited | Send Retry-After |
| 500 Internal Server Error | Unexpected bug | Never leak stack traces |
| 502 / 504 | Upstream failed / timed out | Retryable for idempotent requests |
| 503 Service Unavailable | Overloaded or in maintenance | Send Retry-After |
Never return 200 with an error payload.
Errors: RFC 9457 problem details
Return Content-Type: application/problem+json for every 4xx/5xx:
{
"type": "https://api.example.com/problems/insufficient-funds",
"title": "Insufficient funds",
"status": 422,
"detail": "Balance is 30.00 USD; the transfer needs 50.00 USD.",
"instance": "/v1/transfers/tr_123",
"errors": [{ "pointer": "/amount", "detail": "exceeds available balance" }]
}typeis a stable identifier clients branch on;titleis constant per type;detailis for humans and may change.- Extension members (like
errorsabove, ortraceId) are allowed; document them. - Put field-level validation errors in one response, not one error per round trip.
- Never include secrets, SQL, stack traces or internal hostnames.
Pagination, filtering, sorting
| Cursor (keyset) | Offset | |
| Stable under inserts/deletes | Yes | No (items skip or repeat) |
| Performance on deep pages | Constant | Degrades with offset size |
| Jump to page N | No | Yes |
| Default choice | Yes, for feeds, large or changing data | Small, static admin lists |
- Cursor responses:
{ "data": [...], "nextCursor": "opaque-string-or-null" }. The cursor is opaque (encode the sort key and ID); clients must not parse it. - Always cap
limit(for example default 20, max 100) and document both. - Sort must be deterministic: add the ID as a tiebreaker.
- Filters as query parameters with documented operators:
?status=active&createdAfter=2026-01-01T00:00:00Z. - Sort parameter:
?sort=-createdAt,namewith an allowlist of sortable fields. - Optionally expose
Linkheaders (RFC 8288) withrel="next".
Versioning and compatibility
Non-breaking (ship anytime): adding an endpoint; adding an optional request field; adding a response field; adding an enum value if clients were told enums are extensible; relaxing validation.
Breaking (needs a new version or a migration plan): removing or renaming a field, endpoint or enum value; making an optional field required; changing a type or format; changing default behavior or sort order; tightening validation; changing status codes or error types clients rely on; changing auth requirements; changing pagination style.
Strategies:
| Strategy | Example | When |
| URL major version | /v1/orders | Default for public APIs; simple to route and cache |
| Header or media type | Accept: application/vnd.example.v2+json | When URLs must stay stable |
| Date-based versions | Api-Version: 2026-11-01 | Many small changes; per-client pinning |
Deprecate before removing: announce, mark deprecated: true in OpenAPI, optionally send a Deprecation header (RFC 9745) and a Sunset header (RFC 8594), measure remaining traffic, then remove.
Idempotency keys for POST
Clients retry after timeouts. Without idempotency, a retried POST /payments charges twice.
- Client sends
Idempotency-Key: <uuid>(the header is an IETF draft and is widely used, for example by Stripe). - Server stores key + request fingerprint + response, scoped to the caller, with a TTL (for example 24 hours).
- Same key, same body: return the stored response. Same key, different body: 422 (or 409). Key still in progress: 409.
- Store the key in the same transaction as the side effect, or use a unique constraint, so concurrent duplicates cannot both succeed.
Conditional requests (ETags)
- Return
ETagon GET. Clients sendIf-None-Matchand get 304 when unchanged (saves bandwidth). - For updates, require
If-Match: "<etag>"; return 412 on mismatch to prevent lost updates. Return 428 if the header is missing and you require it. - A version number or
updated_athash is a fine ETag source.
Rate limiting
- Return 429 with
Retry-After(seconds or HTTP date). 503 +Retry-Afterfor overload. - Advertise limits.
RateLimit/RateLimit-Policyheaders are an IETF draft;X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Resetare the common legacy form. Match what the API already uses. - Limit per credential, not only per IP.
Long-running operations
POST /v1/reportsreturns202 Accepted,Location: /v1/operations/op_123.GET /v1/operations/op_123returns{ "status": "running" | "succeeded" | "failed", "result": ..., "error": <problem details> }.- On success, link to the created resource (or
303 See Otherto it). - Optionally offer a webhook on completion. Never hold an HTTP request open for minutes.
Webhooks
- Sign every delivery: HMAC-SHA256 over
id + timestamp + raw bodywith a per-endpoint secret. Consider following the Standard Webhooks specification (standardwebhooks.com); it uses headers along the lines ofwebhook-id,webhook-timestampandwebhook-signature, but check the exact header names and signed-payload format against the current spec before implementing. - Receivers: verify the signature on the raw bytes with a constant-time compare; reject timestamps older than a few minutes (replay protection).
- Delivery is at-least-once: include a unique event ID, retry with exponential backoff, and tell consumers to dedupe by ID.
- Order is not guaranteed: include the resource version or timestamp, or send thin events ("order.updated, id=...") and let receivers fetch current state.
- Receivers should return 2xx fast and process asynchronously.
REST vs GraphQL vs gRPC
| Choose | When |
| REST + OpenAPI | Public or partner APIs, broad client support, HTTP caching matters |
| GraphQL | Many client types with different data needs over one graph; a team that will own schema governance |
| gRPC | Internal service-to-service calls, streaming, strict schemas, polyglot codegen |
Read references/graphql-and-grpc.md when the API is GraphQL or gRPC, or when choosing between them.
Anti-patterns
- Verbs in paths (
/getUser,/createOrder) — use methods on resources. - 200 with
{"error": ...}— breaks every client, proxy and monitor. - Leaking the database schema — internal column names and join tables become a contract you can never change.
- Unbounded lists — every collection endpoint paginates from day one.
- Silent breaking change "because no one uses that field" — prove it with traffic data or version it.
- Retry-unsafe POSTs for money or messages — require an Idempotency-Key.
- Different error shapes per endpoint — one problem-details format everywhere.
- Booleans that will become states (
isActive) — prefer astatusenum when a third state is plausible.
Done when
- OpenAPI spec updated, linted, with examples and every error response documented.
- Breaking-change check run against the previous spec; any breaking change has an agreed plan.
- Errors use problem details; codes match the table; no stack traces leak.
- Collections paginate with a capped limit and deterministic sort.
- Non-idempotent writes that matter accept an Idempotency-Key; updates that can race use ETags.
- Tests cover validation errors, auth failures, pagination edges and retries.
References
- references/review-checklist.md — read when reviewing an API PR or before finishing a design.
- references/graphql-and-grpc.md — read when the interface is GraphQL or gRPC.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

