openapi-spec-generation

Generate, maintain, and validate OpenAPI 3.1 specifications for RESTful APIs. Supports design-first, code-first, and hybrid approaches with templates for complete specs, FastAPI/Python generation, and TypeScript/Express decorators Includes reusable components for schemas, parameters, responses, and security schemes to minimize duplication across endpoints Provides Spectral and Redocly validation rules to enforce naming conventions, security requirements, and documentation standards Enables SDK generation for TypeScript, Python, Go, and other languages via OpenAPI Generator with customizable output options

INSTALLATION
npx skills add https://github.com/wshobson/agents --skill openapi-spec-generation
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

OpenAPI Spec Generation

Comprehensive patterns for creating, maintaining, and validating OpenAPI 3.1 specifications for RESTful APIs.

When to Use This Skill

  • Creating API documentation from scratch
  • Generating OpenAPI specs from existing code
  • Designing API contracts (design-first approach)
  • Validating API implementations against specs
  • Generating client SDKs from specs
  • Setting up API documentation portals

Core Concepts

1. OpenAPI 3.1 Structure

openapi: 3.1.0

info:

  title: API Title

  version: 1.0.0

servers:

  - url: https://api.example.com/v1

paths:

  /resources:

    get: ...

components:

  schemas: ...

  securitySchemes: ...

2. Design Approaches

Approach

Description

Best For

Design-First

Write spec before code

New APIs, contracts

Code-First

Generate spec from code

Existing APIs

Hybrid

Annotate code, generate spec

Evolving APIs

Templates

Template 1: Complete API Specification

openapi: 3.1.0

info:

  title: User Management API

  description: |

    API for managing users and their profiles.

    ## Authentication

    All endpoints require Bearer token authentication.

    ## Rate Limiting

    - 1000 requests per minute for standard tier

    - 10000 requests per minute for enterprise tier

  version: 2.0.0

  contact:

    name: API Support

    email: api-support@example.com

    url: https://docs.example.com

  license:

    name: MIT

    url: https://opensource.org/licenses/MIT

servers:

  - url: https://api.example.com/v2

    description: Production

  - url: https://staging-api.example.com/v2

    description: Staging

  - url: http://localhost:3000/v2

    description: Local development

tags:

  - name: Users

    description: User management operations

  - name: Profiles

    description: User profile operations

  - name: Admin

    description: Administrative operations

paths:

  /users:

    get:

      operationId: listUsers

      summary: List all users

      description: Returns a paginated list of users with optional filtering.

      tags:

        - Users

      parameters:

        - $ref: "#/components/parameters/PageParam"

        - $ref: "#/components/parameters/LimitParam"

        - name: status

          in: query

          description: Filter by user status

          schema:

            $ref: "#/components/schemas/UserStatus"

        - name: search

          in: query

          description: Search by name or email

          schema:

            type: string

            minLength: 2

            maxLength: 100

      responses:

        "200":

          description: Successful response

          content:

            application/json:

              schema:

                $ref: "#/components/schemas/UserListResponse"

              examples:

                default:

                  $ref: "#/components/examples/UserListExample"

        "400":

          $ref: "#/components/responses/BadRequest"

        "401":

          $ref: "#/components/responses/Unauthorized"

        "429":

          $ref: "#/components/responses/RateLimited"

      security:

        - bearerAuth: []

    post:

      operationId: createUser

      summary: Create a new user

      description: Creates a new user account and sends welcome email.

      tags:

        - Users

      requestBody:

        required: true

        content:

          application/json:

            schema:

              $ref: "#/components/schemas/CreateUserRequest"

            examples:

              standard:

                summary: Standard user

                value:

                  email: user@example.com

                  name: John Doe

                  role: user

              admin:

                summary: Admin user

                value:

                  email: admin@example.com

                  name: Admin User

                  role: admin

      responses:

        "201":

          description: User created successfully

          content:

            application/json:

              schema:

                $ref: "#/components/schemas/User"

          headers:

            Location:

              description: URL of created user

              schema:

                type: string

                format: uri

        "400":

          $ref: "#/components/responses/BadRequest"

        "409":

          description: Email already exists

          content:

            application/json:

              schema:

                $ref: "#/components/schemas/Error"

      security:

        - bearerAuth: []

  /users/{userId}:

    parameters:

      - $ref: "#/components/parameters/UserIdParam"

    get:

      operationId: getUser

      summary: Get user by ID

      tags:

        - Users

      responses:

        "200":

          description: Successful response

          content:

            application/json:

              schema:

                $ref: "#/components/schemas/User"

        "404":

          $ref: "#/components/responses/NotFound"

      security:

        - bearerAuth: []

    patch:

      operationId: updateUser

      summary: Update user

      tags:

        - Users

      requestBody:

        required: true

        content:

          application/json:

            schema:

              $ref: "#/components/schemas/UpdateUserRequest"

      responses:

        "200":

          description: User updated

          content:

            application/json:

              schema:

                $ref: "#/components/schemas/User"

        "400":

          $ref: "#/components/responses/BadRequest"

        "404":

          $ref: "#/components/responses/NotFound"

      security:

        - bearerAuth: []

    delete:

      operationId: deleteUser

      summary: Delete user

      tags:

        - Users

        - Admin

      responses:

        "204":

          description: User deleted

        "404":

          $ref: "#/components/responses/NotFound"

      security:

        - bearerAuth: []

        - apiKey: []

components:

  schemas:

    User:

      type: object

      required:

        - id

        - email

        - name

        - status

        - createdAt

      properties:

        id:

          type: string

          format: uuid

          readOnly: true

          description: Unique user identifier

        email:

          type: string

          format: email

          description: User email address

        name:

          type: string

          minLength: 1

          maxLength: 100

          description: User display name

        status:

          $ref: "#/components/schemas/UserStatus"

        role:

          type: string

          enum: [user, moderator, admin]

          default: user

        avatar:

          type: string

          format: uri

          nullable: true

        metadata:

          type: object

          additionalProperties: true

          description: Custom metadata

        createdAt:

          type: string

          format: date-time

          readOnly: true

        updatedAt:

          type: string

          format: date-time

          readOnly: true

    UserStatus:

      type: string

      enum: [active, inactive, suspended, pending]

      description: User account status

    CreateUserRequest:

      type: object

      required:

        - email

        - name

      properties:

        email:

          type: string

          format: email

        name:

          type: string

          minLength: 1

          maxLength: 100

        role:

          type: string

          enum: [user, moderator, admin]

          default: user

        metadata:

          type: object

          additionalProperties: true

    UpdateUserRequest:

      type: object

      minProperties: 1

      properties:

        name:

          type: string

          minLength: 1

          maxLength: 100

        status:

          $ref: "#/components/schemas/UserStatus"

        role:

          type: string

          enum: [user, moderator, admin]

        metadata:

          type: object

          additionalProperties: true

    UserListResponse:

      type: object

      required:

        - data

        - pagination

      properties:

        data:

          type: array

          items:

            $ref: "#/components/schemas/User"

        pagination:

          $ref: "#/components/schemas/Pagination"

    Pagination:

      type: object

      required:

        - page

        - limit

        - total

        - totalPages

      properties:

        page:

          type: integer

          minimum: 1

        limit:

          type: integer

          minimum: 1

          maximum: 100

        total:

          type: integer

          minimum: 0

        totalPages:

          type: integer

          minimum: 0

        hasNext:

          type: boolean

        hasPrev:

          type: boolean

    Error:

      type: object

      required:

        - code

        - message

      properties:

        code:

          type: string

          description: Error code for programmatic handling

        message:

          type: string

          description: Human-readable error message

        details:

          type: array

          items:

            type: object

            properties:

              field:

                type: string

              message:

                type: string

        requestId:

          type: string

          description: Request ID for support

  parameters:

    UserIdParam:

      name: userId

      in: path

      required: true

      description: User ID

      schema:

        type: string

        format: uuid

    PageParam:

      name: page

      in: query

      description: Page number (1-based)

      schema:

        type: integer

        minimum: 1

        default: 1

    LimitParam:

      name: limit

      in: query

      description: Items per page

      schema:

        type: integer

        minimum: 1

        maximum: 100

        default: 20

  responses:

    BadRequest:

      description: Invalid request

      content:

        application/json:

          schema:

            $ref: "#/components/schemas/Error"

          example:

            code: VALIDATION_ERROR

            message: Invalid request parameters

            details:

              - field: email

                message: Must be a valid email address

    Unauthorized:

      description: Authentication required

      content:

        application/json:

          schema:

            $ref: "#/components/schemas/Error"

          example:

            code: UNAUTHORIZED

            message: Authentication required

    NotFound:

      description: Resource not found

      content:

        application/json:

          schema:

            $ref: "#/components/schemas/Error"

          example:

            code: NOT_FOUND

            message: User not found

    RateLimited:

      description: Too many requests

      content:

        application/json:

          schema:

            $ref: "#/components/schemas/Error"

      headers:

        Retry-After:

          description: Seconds until rate limit resets

          schema:

            type: integer

        X-RateLimit-Limit:

          description: Request limit per window

          schema:

            type: integer

        X-RateLimit-Remaining:

          description: Remaining requests in window

          schema:

            type: integer

  examples:

    UserListExample:

      value:

        data:

          - id: "550e8400-e29b-41d4-a716-446655440000"

            email: "john@example.com"

            name: "John Doe"

            status: "active"

            role: "user"

            createdAt: "2024-01-15T10:30:00Z"

        pagination:

          page: 1

          limit: 20

          total: 1

          totalPages: 1

          hasNext: false

          hasPrev: false

  securitySchemes:

    bearerAuth:

      type: http

      scheme: bearer

      bearerFormat: JWT

      description: JWT token from /auth/login

    apiKey:

      type: apiKey

      in: header

      name: X-API-Key

      description: API key for service-to-service calls

security:

  - bearerAuth: []

For advanced code-first generation patterns and tooling, see references/code-first-and-tooling.md:

  • Template 2: Python/FastAPI — Pydantic models with Field validation, enum types, full CRUD endpoints with response_model and status_code, exporting the spec as JSON
  • Template 3: TypeScript/tsoa — Decorator-based controllers (@Route, @Get, @Security, @Example, @Response) that generate OpenAPI from TypeScript types
  • Template 4: Validation & Linting — Spectral ruleset (.spectral.yaml) with custom rules for operationId, security, naming conventions; Redocly config with MIME type enforcement and code sample generation
  • SDK Generationopenapi-generator-cli for TypeScript (fetch), Python, and Go clients

Best Practices

Do's

  • Use $ref - Reuse schemas, parameters, responses
  • Add examples - Real-world values help consumers
  • Document errors - All possible error codes
  • Version your API - In URL or header
  • Use semantic versioning - For spec changes

Don'ts

  • Don't use generic descriptions - Be specific
  • Don't skip security - Define all schemes
  • Don't forget nullable - Be explicit about null
  • Don't mix styles - Consistent naming throughout
  • Don't hardcode URLs - Use server variables
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card