# Generate API Docs

> Generate API reference documentation from existing route definitions, controllers, and schemas. Produces a markdown API reference or OpenAPI YAML spec. Use when the API has no docs, outdated Swagger, or the team wants a readable markdown reference.

- Skill: `gabrielmoreira/generate-api-docs` (Agent Skill)
- Install (CLI): `npx skillmds@latest add gabrielmoreira/generate-api-docs`
- Raw SKILL.md: https://api.skillmd.com/api/skills/gabrielmoreira/generate-api-docs/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: gabrielmoreira (https://skillmd.com/u/gabrielmoreira)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/gabrielmoreira/generate-api-docs

---


# Generate API Documentation

Produce complete, accurate API documentation by reading route files, controllers, and schema definitions directly.

## When to Use

- API has no documentation
- Swagger/OpenAPI spec is missing or outdated
- Team wants a human-readable markdown API reference
- Preparing docs to push to Confluence or a developer portal

## Step 1: Locate API Definitions

Search for route/endpoint definitions in this priority order:

**Express/Node.js:**
- Router files: `src/routes/`, `src/api/routes/`, `app/routes/`
- Controller files: `src/controllers/`, `src/api/controllers/`
- Main app file where routes are registered

**FastAPI/Python:**
- Router files: `app/routers/`, `src/api/`
- `main.py` or `app.py` where routes are registered
- Pydantic models for request/response schemas

**NestJS:**
- `*.controller.ts` files
- `*.module.ts` for route grouping
- DTO files: `*.dto.ts`

**Spring Boot:**
- `@RestController` annotated classes
- `@RequestMapping`, `@GetMapping`, etc.
- Request/response DTO classes

**Other:**
- OpenAPI spec files: `openapi.yaml`, `swagger.json`, `api-spec.yaml`
- `.proto` files (gRPC)
- GraphQL schema files: `schema.graphql`, `typeDefs.ts`

## Step 2: Extract Endpoint Information

For each endpoint, capture:

```
Method:    GET / POST / PUT / PATCH / DELETE
Path:      /api/v1/users/:id
Auth:      required (JWT) | optional | none
Summary:   Get user by ID
Handler:   UserController.getById (file:line)

Path params:
  id  UUID  User's unique identifier

Query params:
  include  string (optional)  Comma-separated relations to include (e.g., "posts,sessions")

Request body: (if applicable)
  {JSON schema or TypeScript interface}

Response 200:
  {shape found in controller return statement or serializer}

Response codes:
  200  Success
  400  Validation error
  401  Unauthenticated
  403  Unauthorized
  404  Not found
  500  Internal error
```

## Step 3: Extract Auth Requirements

Document globally:
- What auth scheme is used (JWT, API Key, Session, OAuth2)
- How to obtain credentials (if visible in auth routes)
- Where to pass them (Authorization header, query param, cookie)
- Which endpoints are public vs protected

## Step 4: Extract Common Error Formats

Find the error response shape (look at error middleware or existing 4xx/5xx responses):

```json
{
  "message": "string",
  "code": "string",
  "details": {}
}
```

## Step 5: Output Format Choice

Ask: "Which format do you need?"
- **A** — Markdown API reference (human-readable, good for Confluence/GitHub)
- **B** — OpenAPI 3.0 YAML (machine-readable, Swagger UI compatible)
- **C** — Both

---

## Output A: API_REFERENCE.md

Write to: `{project-root}/docs/API_REFERENCE.md`

```markdown
# API Reference — {project_name}

> Generated by Scout on {date}. Source: route files in `{src/api/}`.

## Base URL

`{/api/v1}` (configure via {BASE_URL} env var)

## Authentication

**Type:** {JWT Bearer Token}

Include token in all authenticated requests:
```
Authorization: Bearer <your_token>
```

Obtain token via: `POST /auth/login`

---

## Resources

### Users

#### GET /users
List users.

**Auth:** Required  
**Query params:**
| Param | Type | Default | Description |
|-------|------|---------|-------------|
| page | number | 1 | Page number |
| limit | number | 20 | Results per page |

**Response 200:**
```json
{
  "data": [{ "id": "uuid", "email": "string", "name": "string" }],
  "total": 100,
  "page": 1
}
```

---

#### POST /users
Create a user.

{... and so on per endpoint ...}

---

## Error Responses

All errors follow this format:
```json
{
  "message": "Human-readable error",
  "code": "MACHINE_READABLE_CODE"
}
```

| HTTP Code | Meaning |
|-----------|---------|
| 400 | Validation error — check `details` field |
| 401 | Missing or invalid token |
| 403 | Insufficient permissions |
| 404 | Resource not found |
| 500 | Internal server error |
```

---

## Output B: openapi.yaml

Write to: `{project-root}/docs/openapi.yaml`

```yaml
openapi: "3.0.3"
info:
  title: {project_name} API
  version: "{version from package.json or 1.0.0}"
  description: "{description}"
servers:
  - url: http://localhost:{PORT}/api/v1
    description: Local development

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    {User}:
      type: object
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
      required: [id, email]
    Error:
      type: object
      properties:
        message: { type: string }
        code: { type: string }

paths:
  /users:
    get:
      summary: List users
      security:
        - BearerAuth: []
      parameters:
        - name: page
          in: query
          schema: { type: integer, default: 1 }
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
```

## Handling Undocumented Behaviors

If a handler doesn't have clear response typing:
- Trace through the controller to the service return value
- Note: `> Response shape inferred from service return type — verify before publishing`

## TODOs

Mark any endpoint that couldn't be fully documented:
```
<!-- TODO: Response shape for GET /users/:id/posts not determinable — 
     UserController.getPosts has implicit any return type -->
```

List all TODOs at the end so user knows what needs manual review.

