opencode-workflow/skills/be-api-design/SKILL.md

12 KiB

name description
be-api-design Backend Agent uses this skill to design API specs. Based on PRD, produce OpenAPI 3.0 spec including endpoints, request/response structures, error handling. Trigger: After PRD approved (Stage 4).

/be-api-design — API Design

Backend Agent uses this skill to design API specs.

Responsibilities

  1. Analyze functional requirements from PRD
  2. Use design-an-interface to explore multiple API design options
  3. Design RESTful API endpoints
  4. Define request/response schemas
  5. Design error handling mechanism
  6. Produce OpenAPI 3.0 spec

Input

  • PRD document (docs/prd/{date}-{feature}.md)
  • Existing API style (existing API specs in project)
  • Data model context

Output

  • API spec document: docs/api/{date}-{feature}.yaml (OpenAPI 3.0)

Flow

Read PRD
    ↓
Identify resources and operations
    ↓
Call design-an-interface to explore 2-3 design options
    ↓
Select best option
    ↓
Define OpenAPI Schema
    ↓
Design error handling
    ↓
Security review
    ↓
Produce OpenAPI document

Step Details

1. Read PRD

Extract all functional requirements from PRD, identify:

  • Resources (nouns): users, orders, products, etc.
  • Operations (verbs): create, read, update, delete, etc.
  • Relationships: relationships between resources (one-to-many, many-to-many)
  • Non-functional requirements: pagination, rate limiting, authentication, etc.

2. Identify Resources and Operations

Map functional requirements to RESTful resources:

  • Each noun → potential resource
  • Each verb → HTTP method
  • Each relationship → nested resource or standalone endpoint

3. Call design-an-interface

Use design-an-interface skill to generate 2-3 distinct API design options:

  • Option A: Minimize method count (1-3 endpoints per resource)
  • Option B: Maximize flexibility (support multiple use cases)
  • Option C: Optimize for most common operations

Compare pros and cons, select best design.

4. Define OpenAPI Schema

Use template below to produce complete OpenAPI 3.0 spec.

5. Security Review

Ensure all endpoints have appropriate authentication and permission controls.

6. Produce Document

Save to docs/api/{date}-{feature}.yaml.

Design Principles

RESTful Design

Resource-oriented:
  - URL represents resource, not action
  - HTTP methods represent actions

Example:
  GET    /api/v1/users              # List users
  GET    /api/v1/users/{id}         # Get specific user
  POST   /api/v1/users              # Create user
  PUT    /api/v1/users/{id}         # Full update
  PATCH  /api/v1/users/{id}         # Partial update
  DELETE /api/v1/users/{id}         # Delete user

Nested resources:
  GET    /api/v1/users/{id}/orders  # Get user's orders
  POST   /api/v1/users/{id}/orders  # Create order for user

HTTP Status Codes

Success:
  200: OK                          # GET, PUT, PATCH, DELETE success
  201: Created                     # POST successfully created resource
  204: No Content                  # DELETE success, no response body

Client Error:
  400: Bad Request                 # Request format error
  401: Unauthorized                # Not authenticated
  403: Forbidden                   # No permission
  404: Not Found                   # Resource not found
  409: Conflict                    # Resource conflict (e.g., duplicate)
  422: Unprocessable Entity        # Validation error
  429: Too Many Requests           # Rate limit

Server Error:
  500: Internal Server Error       # Server internal error
  502: Bad Gateway                 # Upstream service error
  503: Service Unavailable         # Service temporarily unavailable

Response Format

Success response:
  type: object
  properties:
    data:
      type: object
    meta:
      type: object
      properties:
        page:
          type: integer
        limit:
          type: integer
        total:
          type: integer
        total_pages:
          type: integer

Error response:
  type: object
  properties:
    error:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
        details:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
              message:
                type: string

OpenAPI 3.0 Template

openapi: 3.0.3
info:
  title: {API Name}
  version: 1.0.0
  description: |
    {Description}

    Related PRD: {PRD Link}    

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

paths:
  /users:
    get:
      summary: List users
      tags:
        - Users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
        - name: search
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'

    post:
      summary: Create user
      tags:
        - Users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: Created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '422':
          $ref: '#/components/responses/ValidationError'

  /users/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string

    get:
      summary: Get user
      tags:
        - Users
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserResponse'
        '404':
          $ref: '#/components/responses/NotFound'

    put:
      summary: Full update user
      tags:
        - Users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: Updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserResponse'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'

    patch:
      summary: Partial update user
      tags:
        - Users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchUserRequest'
      responses:
        '200':
          description: Updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserResponse'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      summary: Delete user
      tags:
        - Users
      responses:
        '204':
          description: Deleted successfully
        '404':
          $ref: '#/components/responses/NotFound'

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
          example: "usr_123456"
        email:
          type: string
          format: email
          example: "user@example.com"
        name:
          type: string
          example: "John Doe"
        status:
          type: string
          enum: [active, inactive, suspended]
          example: "active"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - email
        - name
        - status
        - created_at
        - updated_at

    CreateUserRequest:
      type: object
      properties:
        email:
          type: string
          format: email
        password:
          type: string
          minLength: 8
        name:
          type: string
          minLength: 1
          maxLength: 100
      required:
        - email
        - password
        - name

    UpdateUserRequest:
      type: object
      properties:
        email:
          type: string
          format: email
        name:
          type: string
          minLength: 1
          maxLength: 100
        status:
          type: string
          enum: [active, inactive]

    PatchUserRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        status:
          type: string
          enum: [active, inactive]

    UserResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/User'

    UserListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        meta:
          type: object
          properties:
            page:
              type: integer
            limit:
              type: integer
            total:
              type: integer
            total_pages:
              type: integer

    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  field:
                    type: string
                  message:
                    type: string

  responses:
    BadRequest:
      description: Request format error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    Unauthorized:
      description: Not authenticated
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    ValidationError:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    InternalError:
      description: Server internal error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

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

security:
  - bearerAuth: []

Design Checklist

Security

  • All endpoints have appropriate authentication
  • Input validation complete
  • Rate limiting designed
  • CORS configured

Performance

  • Pagination support
  • Caching strategy
  • Batch operation support

Reliability

  • Error response format unified
  • Retry mechanism recommendations
  • Idempotency design

Consistency

  • Naming convention consistent (resources use plural nouns)
  • Response format consistent (data/meta/error structure)
  • Filter/sort/pagination parameters consistent
  • Prerequisite: write-a-prd (after PRD approved)
  • 辅助: design-an-interface (explore multiple design options)
  • Follow-up: dba-schema (DB Schema design)
  • Rollback: Can rollback to write-a-prd to modify requirements

Rollback Mechanism

Design Review rejects API design
    ↓
Modify OpenAPI spec
    ↓
Re-submit (or re-call design-an-interface)

DBA Agent finds Schema conflict
    ↓
Negotiate domain model or API response format adjustments
    ↓
Update OpenAPI spec