Skip to content

API Design

IntermediateDocumentation

Design and validate APIs with schema generation, documentation, and contract testing. This pipeline helps you create well-documented, consistent APIs with OpenAPI specifications.

Prerequisites

  • Wave installed and initialized (wave init)
  • Understanding of REST/HTTP API design principles
  • Experience with documentation-generation pipeline (recommended)
  • Familiarity with OpenAPI/Swagger specifications

Quick Start

bash
wave run api-design "design REST API for user management (CRUD operations)"

Expected output:

[10:00:01] started   requirements      (navigator)              Starting step
[10:00:28] completed requirements      (navigator)   27s   2.4k Requirements complete
[10:00:29] started   design            (philosopher)            Starting step
[10:01:15] completed design            (philosopher)  46s   5.8k Design complete
[10:01:16] started   validate          (auditor)                Starting step
[10:01:42] completed validate          (auditor)     26s   2.1k Validation complete

Pipeline api-design completed in 101s
Artifacts: .wave/output/api-spec.yaml

Complete Pipeline

Save the following YAML to .wave/pipelines/api-design.yaml:

yaml
kind: WavePipeline
metadata:
  name: api-design
  description: "Design and document APIs with OpenAPI specification"

input:
  source: cli

steps:
  - id: requirements
    persona: navigator
    memory:
      strategy: fresh
    workspace:
      mount:
        - source: ./
          target: /src
          mode: readonly
    exec:
      type: prompt
      source: |
        Gather API requirements for: {{ input }}

        Analyze:
        1. What resources need to be exposed?
        2. What operations are needed (CRUD, custom actions)?
        3. What data models are involved?
        4. What are the authentication/authorization requirements?
        5. What are the performance requirements?
        6. Are there existing APIs to maintain consistency with?

        Output as JSON:
        {
          "resources": [{"name": "", "description": "", "operations": []}],
          "data_models": [{"name": "", "fields": []}],
          "authentication": "",
          "rate_limits": {},
          "existing_patterns": []
        }
    output_artifacts:
      - name: requirements
        path: .wave/output/api-requirements.json
        type: json

  - id: design
    persona: philosopher
    dependencies: [requirements]
    memory:
      strategy: fresh
      inject_artifacts:
        - step: requirements
          artifact: requirements
          as: requirements
    exec:
      type: prompt
      source: |
        Design the API based on requirements: {{ input }}

        Create an OpenAPI 3.0 specification including:
        1. Info and server configuration
        2. Paths for all endpoints
        3. Request/response schemas
        4. Authentication schemes
        5. Error responses
        6. Examples for each endpoint

        Follow best practices:
        - RESTful naming conventions
        - Consistent response structure
        - Meaningful HTTP status codes
        - Pagination for list endpoints
        - Versioning strategy
        - HATEOAS links where appropriate
    output_artifacts:
      - name: spec
        path: .wave/output/api-spec.yaml
        type: yaml

  - id: validate
    persona: auditor
    dependencies: [design]
    memory:
      strategy: fresh
      inject_artifacts:
        - step: requirements
          artifact: requirements
          as: requirements
        - step: design
          artifact: spec
          as: api_spec
    exec:
      type: prompt
      source: |
        Validate the API design:

        Check:
        1. All requirements addressed?
        2. OpenAPI spec is valid?
        3. Naming conventions consistent?
        4. Error handling comprehensive?
        5. Security considerations addressed?
        6. Pagination implemented for collections?
        7. Versioning strategy clear?
        8. Documentation complete?

        Output: list of issues or "APPROVED"
    output_artifacts:
      - name: validation
        path: .wave/output/api-validation.md
        type: markdown

Expected Outputs

The pipeline produces three artifacts:

ArtifactPathDescription
requirements.wave/output/api-requirements.jsonStructured API requirements
spec.wave/output/api-spec.yamlOpenAPI 3.0 specification
validation.wave/output/api-validation.mdDesign review and validation

Example Output

The pipeline produces .wave/output/api-spec.yaml:

yaml
openapi: 3.0.3
info:
  title: User Management API
  description: REST API for user management operations
  version: 1.0.0
  contact:
    name: API Support
    email: api@example.com

servers:
  - url: https://api.example.com/v1
    description: Production server
  - url: https://staging-api.example.com/v1
    description: Staging server

paths:
  /users:
    get:
      summary: List all users
      description: Retrieve a paginated list of users
      operationId: listUsers
      tags:
        - Users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
        - name: sort
          in: query
          schema:
            type: string
            enum: [created_at, name, email]
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserList'
        '401':
          $ref: '#/components/responses/Unauthorized'

    post:
      summary: Create a new user
      description: Create a new user account
      operationId: createUser
      tags:
        - Users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: User created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          $ref: '#/components/responses/BadRequest'
        '409':
          $ref: '#/components/responses/Conflict'

  /users/{userId}:
    get:
      summary: Get a user by ID
      operationId: getUser
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/UserId'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          $ref: '#/components/responses/NotFound'

    put:
      summary: Update a user
      operationId: updateUser
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/UserId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: User updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      summary: Delete a user
      operationId: deleteUser
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/UserId'
      responses:
        '204':
          description: User deleted
        '404':
          $ref: '#/components/responses/NotFound'

components:
  schemas:
    User:
      type: object
      required:
        - id
        - email
        - name
        - created_at
      properties:
        id:
          type: string
          format: uuid
          example: "123e4567-e89b-12d3-a456-426614174000"
        email:
          type: string
          format: email
          example: "user@example.com"
        name:
          type: string
          example: "John Doe"
        role:
          type: string
          enum: [admin, user, guest]
          default: user
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    UserList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        pagination:
          $ref: '#/components/schemas/Pagination'

    CreateUserRequest:
      type: object
      required:
        - email
        - name
        - password
      properties:
        email:
          type: string
          format: email
        name:
          type: string
          minLength: 1
          maxLength: 100
        password:
          type: string
          minLength: 8
        role:
          type: string
          enum: [admin, user, guest]

    UpdateUserRequest:
      type: object
      properties:
        name:
          type: string
        role:
          type: string
          enum: [admin, user, guest]

    Pagination:
      type: object
      properties:
        page:
          type: integer
        limit:
          type: integer
        total:
          type: integer
        total_pages:
          type: integer

    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
        message:
          type: string
        details:
          type: object

  parameters:
    UserId:
      name: userId
      in: path
      required: true
      schema:
        type: string
        format: uuid

  responses:
    BadRequest:
      description: Bad request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Conflict:
      description: Resource conflict
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

security:
  - bearerAuth: []

Customization

Design specific API type

bash
wave run api-design "design GraphQL API for product catalog"
bash
wave run api-design "design WebSocket API for real-time notifications"

Include implementation

Add a code generation step:

yaml
- id: implement
  persona: craftsman
  dependencies: [design]
  memory:
    inject_artifacts:
      - step: design
        artifact: spec
        as: api_spec
  exec:
    source: |
      Generate Go handler stubs from the OpenAPI spec.
      Include:
      - Handler interfaces
      - Request/response types
      - Validation middleware
      - Router configuration
  output_artifacts:
    - name: handlers
      path: .wave/output/handlers.go
      type: code

Add contract tests

yaml
- id: contract-tests
  persona: craftsman
  dependencies: [design]
  memory:
    inject_artifacts:
      - step: design
        artifact: spec
        as: api_spec
  exec:
    source: |
      Generate contract tests from the OpenAPI spec.
      Test each endpoint for:
      - Valid requests
      - Invalid requests (validation errors)
      - Error responses
      - Edge cases
  handover:
    contract:
      type: test_suite
      command: "go test ./api/... -v"
      must_pass: true
  output_artifacts:
    - name: tests
      path: .wave/output/api_test.go
      type: code

API Design Best Practices

Naming Conventions

  • Use plural nouns for collections: /users, /orders
  • Use kebab-case for multi-word paths: /user-preferences
  • Use query params for filtering: /users?role=admin

HTTP Methods

MethodPurposeExample
GETRetrieve resource(s)GET /users/123
POSTCreate resourcePOST /users
PUTReplace resourcePUT /users/123
PATCHPartial updatePATCH /users/123
DELETERemove resourceDELETE /users/123

Response Codes

CodeMeaningUse Case
200OKSuccessful GET, PUT, PATCH
201CreatedSuccessful POST
204No ContentSuccessful DELETE
400Bad RequestValidation error
401UnauthorizedMissing/invalid auth
403ForbiddenInsufficient permissions
404Not FoundResource doesn't exist
409ConflictDuplicate resource
429Too Many RequestsRate limited
500Server ErrorUnexpected error

Next Steps

Released under the MIT License.