api-spec-builder — Turn a Prose Feature Description into OpenAPI YAML

Single-file Claude skill that takes a prose description of an API feature ("we need to let users search orders by date and status") and produces a valid OpenAPI 3.1 YAML fragment with paths, schemas, and example responses, ready to paste into your spec.

api-spec-builder takes a prose description of an API feature — “we need to let users search orders by date range and status, returning a paginated list” — and produces a valid OpenAPI 3.1 YAML fragment with paths, request schemas, response schemas, error shapes, and a working example response.

Designed for the moment when you’re about to start building a new endpoint and you’d rather review a YAML than write one from scratch.

At a glance

Field Value
Name api-spec-builder
Version 1.0.0
Files 1 file (SKILL.md)
Runtime None — pure prompting
Triggers on “write OpenAPI for…”, “spec out an endpoint that…”, “I need an API to…”, “draft the schema for a search endpoint”, “turn this requirement into OpenAPI”
Does NOT trigger on generating server code from a spec, generating a TypeScript SDK, designing the database schema

Step 1 — Create the folder

bash
mkdir -p ~/.claude/skills/api-spec-builder

Windows:

powershell
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\skills\api-spec-builder" | Out-Null

Step 2 — Paste this file

Path: ~/.claude/skills/api-spec-builder/SKILL.md

markdown
---
name: api-spec-builder
description: Use this skill whenever the user describes an API feature in prose and wants the OpenAPI 3.1 YAML for it. Trigger on "write OpenAPI for…", "spec out an endpoint that…", "I need an API to…", "draft the schema for a search endpoint", "turn this requirement into OpenAPI". Do NOT use for generating server-side code from a spec, building a TypeScript SDK, or designing the database schema — those are downstream jobs handled by other skills.
version: 1.0.0
---

# api-spec-builder

Takes a prose feature description and produces a valid OpenAPI 3.1 YAML fragment ready to paste into the project's `openapi.yaml`.

## When invoked

If the prose is missing something obvious, ask ONE clarifying question covering all the gaps in a single turn. Do not Q&A-loop the user. Default to sensible REST conventions:

- Resource collections: `GET /resource`, `POST /resource`
- Single resource: `GET /resource/{id}`, `PATCH /resource/{id}`, `DELETE /resource/{id}`
- Sub-resources: `GET /resource/{id}/sub-resource`
- Search: `POST /resource/search` (not GET — search inputs grow beyond URL limits)
- Filters: query params for simple cases; POST body for complex
- Pagination: cursor-based (`cursor`, `limit`) — not page numbers
- Auth: `bearer` token via `Authorization` header

## Output structure

Always emit YAML with these sections in this order:

    paths:
      /your/endpoint:
        method:
          summary: …
          description: …
          tags: [resource]
          parameters:           # query/path/header
            - …
          requestBody:          # if applicable
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/X'
          responses:
            '200': …
            '400': …
            '401': …
            '404': …            # if path has {id}
          security:
            - bearerAuth: []

    components:
      schemas:
        X:
          type: object
          required: […]
          properties: { … }
        Y: …
      responses:
        Error:                  # reusable error envelope
          description: …
          content: …
      securitySchemes:
        bearerAuth:
          type: http
          scheme: bearer

The fragment must be valid OpenAPI 3.1 (note: 3.1 uses JSON Schema 2020-12 — `nullable` is replaced by `type: [string, "null"]`).

## Schema rules

- Every property has a `description` (one short sentence) and an `example`.
- Strings have `minLength`/`maxLength` if there's any reasonable bound.
- Numbers have `minimum`/`maximum` where they exist.
- Enums use `enum:` with all valid values listed; do NOT make up values.
- IDs are strings (UUID or opaque), not integers, unless the user specifies otherwise.
- Timestamps are `string` with `format: date-time` (ISO 8601).
- Money is an object `{ amount_minor: integer, currency: string }`, not a float.

## Error responses

Always include a reusable `Error` response component with this shape and reference it from `400/401/404/409/422/500`:

    type: object
    required: [code, message]
    properties:
      code:    { type: string, example: invalid_argument }
      message: { type: string, example: "limit must be between 1 and 100" }
      details: { type: array, items: { type: object } }

Per-endpoint, only list the response codes that actually apply. Don't carpet-bomb every code.

## Example responses

Every `200` (and `201` where applicable) gets an `example` block under `content.application/json` with realistic-looking data — not "string", not "lorem ipsum". Make IDs look like real IDs, dates like real dates, money like real money. The example is the spec's most-read line; treat it as documentation.

## When NOT to use

- Generating server code → different skill (codegen)
- Building TypeScript/Python SDKs from the spec → SDK-gen skill
- Designing the database schema behind the API → data-model skill

## Output

Print the YAML in a single fenced code block. No preamble. If the user wants the file written to disk, they'll ask — default is paste-back.

Step 3 — Restart Claude Code

bash
/clear

or quit and re-open the CLI.

Step 4 — Try it

text
Write the OpenAPI for an endpoint that lets a logged-in user
search their orders by date range, status (one of: pending,
shipped, delivered, cancelled), and an optional text query
on order notes. Return paginated results, max 50 per page.

The skill produces a POST /orders/search endpoint with cursor pagination, a request body schema with date range + enum status + free-text query, a response with orders array + next_cursor, an Order schema with realistic example IDs and timestamps, plus error responses for 400 / 401 / 422.

Customising

  • Pin your project’s auth scheme. Replace the securitySchemes block in SKILL.md with the one your project uses (API key, OAuth2, mTLS).
  • Different ID format. If your project uses snowflake IDs or hashids, edit the “IDs are strings” line to specify the format and pattern.
  • Stricter error envelope. If your team uses Problem Details (RFC 7807), replace the Error component spec with the RFC 7807 shape.

More skills in the Skill Library. For testing changes to this skill before shipping them, see Testing a Skill Before You Ship It.