Api contract draft
Draft an OpenAPI 3.1 contract from a feature brief or story — resource-oriented paths, a full error catalog (RFC 9457), pagination/idempotency/versioning decided not deferred, examples on every operation, plus a decisions log so review argues choices instead of YAML. Use when the user wants to design an API, draft an OpenAPI/Swagger spec, define request/response shapes, or agree a contract between frontend/backend or two teams before code.From its SKILL.md
npx -y skills add sananthanarayan/skilldrop --skill api-contract-draftAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.6 KB, as published. Nobody here has run it
api-contract-draft
Produces the contract before the code — a valid OpenAPI 3.1 document two teams can argue about and then build against in parallel. The YAML is half the artifact; the other half is the decisions log, because reviewers should debate "cursor vs offset pagination", not line 240. Designs new contracts; documenting an existing API is guide-builder's job.
How to respond
-
Extract the resources from the brief. Nouns the API owns, their relationships, and their lifecycle (who creates, what mutates, is delete real or soft). Ask at most 2 questions, and spend them on consumer shape ("who calls this — our SPA, partners, both?") and write semantics ("can a refund be requested twice?") — the two answers that change the contract most. Everything else: pick the convention from
reference.mdand tag the choice[assumption]in the decisions log. -
Apply the house conventions (full detail in
reference.md) — deviate only when the brief forces it, and log the deviation:- Paths: plural-noun resources, no verbs — ✅
POST /refunds❌POST /createRefund; nesting one level max, then flatten with filters - Errors: RFC 9457
application/problem+json, every 4xx the operation can return enumerated with a stable machine-readablecode; no bare unexplained 500 - Pagination: cursor-based by default (
cursor+limit, response carriesnext_cursor); offset only with a logged reason - Idempotency: every unsafe POST takes
Idempotency-Key; PUT/DELETE idempotent by construction - Versioning: URL major version (
/v1/), additive changes don't bump, breaking changes do — the policy sentence goes in the spec'sdescription - Auth: a
securitySchemeexists and every operation declares its requirement — including the explicitly-public ones
- Paths: plural-noun resources, no verbs — ✅
-
Type every field like a reviewer will reject sloppiness. Formats (
uuid,date-time,int64), constraints (maxLength,minimum,enum,patternfor codes), required vs optional explicit on every schema, money as integer minor units (never float), timestamps UTC ISO-8601. A schema that's all baretype: stringis a draft of a draft. -
Give every operation a realistic example — request and the 2xx response, with values that look like production (
"cur_9f3k...", not"string"). Examples are where shape disagreements surface; they're the cheapest review tool in the document. -
Emit three sections in one message:
- Decisions log — table of every contract decision (resource naming, pagination, error model, versioning, auth, the
[assumption]s) with a one-line rationale each - The OpenAPI 3.1 YAML — complete and valid:
info(with the versioning policy),servers,components.securitySchemes,components.schemas(including theProblemschema), paths with examples - Open questions — the unknowns that block freezing the contract, each with who can answer it
Start from
templates/openapi-skeleton.yaml.
- Decisions log — table of every contract decision (resource naming, pagination, error model, versioning, auth, the
-
For event/queue contracts (the brief says "publish", "consume", "webhook out"): same discipline, AsyncAPI-shaped — channel name, payload schema with the same typing rigor, delivery semantics stated (at-least-once is the default; say it), and the consumer-retry/DLQ expectation in the channel description.
Useful references in this skill
reference.md— the house conventions: naming, errors, pagination, idempotency, versioning, field-typing rulestemplates/openapi-skeleton.yaml— valid 3.1 starting point withProblemschema, security scheme, and one fully-worked resource
Quality bar
- The YAML validates. OpenAPI 3.1, parseable, refs resolve. A contract that doesn't lint is a sketch.
- Every operation enumerates its 4xx set with stable
codevalues a client can switch on. "400: Bad Request" alone is an unwritten error contract. - Every decision in the log has a rationale, and every deviation from
reference.mdconventions is logged as a decision — silent deviation is how two services end up with three pagination styles. - Examples look like production data.
"id": "string"in an example means nobody pictured a real call. - No float money, no naked timestamps, no stringly-typed enums. The three classic contract regrets, all preventable at draft time.
- Unsafe operations state their idempotency story. A reviewer can answer "what happens on retry?" for every POST.
When to use this skill
- ✅ Designing a new API or new resource before implementation
- ✅ Frontend and backend (or two teams) need a contract to build against in parallel
- ✅ A story from
user-story-splitterwhose slice is "expose X over the API" - ✅ Drafting the webhook/event contract a partner will consume
When NOT to use this skill
- ❌ Documenting an API that already exists — that's
guide-builder(reference archetype) - ❌ Choosing REST vs GraphQL vs gRPC — that's
tech-comparison-matrix; this skill starts after - ❌ Reviewing a contract someone else drafted —
doc-critiqueorcouncil-review - ❌ Generating server/client code from the spec — hand the frozen contract to the codegen tool
Anti-patterns to avoid
- ❌ RPC verbs in paths (
/getUser,/doRefund). The resource model is the contract's spine; verbs mean it was never designed. - ❌ The 200-with-error-body.
200 {"success": false}breaks every client's error handling; failures use failure status codes. - ❌ Deferring pagination "until we need it". Retrofitting pagination onto a shipped list endpoint is a breaking change; decide it at draft.
- ❌ One giant shared schema reused for create-request, update-request, and response, with half the fields "ignored on input". Separate the shapes; optionality differs.
- ❌ YAML without the decisions log. Reviewers nitpick property names and never see that offset pagination or float money slipped through.
- ❌ Contract churn after parallel build starts. Once both sides build, every change is a versioned change — the open-questions section exists to drain before freezing, not after.