← Back to Guides
Use CasesCreating API Documentation in Markdown
Published on 2026-02-22

Creating API Documentation in Markdown

How to write clear, complete, and maintainable API documentation using Markdown — covering endpoints, request/response schemas, code examples, and authentication.

API documentation is the face of your API. Good API docs turn a confusing interface into a joy to use — and bad ones turn a great API into an abandoned one. This guide covers how to write excellent API documentation in Markdown.

What Good API Docs Include

At a minimum, every API should document:

  1. Authentication — how to obtain and pass credentials
  2. Base URL — the root URL for all endpoints
  3. Endpoints — path, method, parameters, request body, response
  4. Error codes — what failure responses look like
  5. Rate limits — how many requests are allowed
  6. Code examples — working code in multiple languages

Document Structure

markdown
# My API Reference

## Overview
## Authentication
## Rate Limiting
## Endpoints
  ### Users
    #### GET /users
    #### POST /users
    #### GET /users/{id}
    #### PUT /users/{id}
    #### DELETE /users/{id}
  ### Documents
    #### GET /documents
    ...
## Error Reference
## Changelog

Documenting Authentication

markdown
## Authentication

All API requests require a bearer token in the `Authorization` header.

**Obtaining a token:**

```bash
curl -X POST https://api.example.com/auth/token \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "password": "secret"}'

Response:

json
{
  "access_token": "eyJhbGciOiJIUzI1...",
  "token_type": "bearer",
  "expires_in": 3600
}

Using the token:

bash
curl https://api.example.com/api/users \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1..."

## Documenting an Endpoint

Use a consistent template for every endpoint:

```markdown
### GET /api/documents

Returns a paginated list of documents belonging to the authenticated user.

**Query Parameters**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `page` | integer | `1` | Page number |
| `per_page` | integer | `20` | Results per page (max: 100) |
| `is_public` | boolean | — | Filter by visibility |
| `search` | string | — | Full-text search query |

**Example Request**

```bash
curl "https://api.example.com/api/documents?page=1&per_page=10" \
  -H "Authorization: Bearer {token}"

Example Response

json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "title": "Q1 Report",
      "is_public": false,
      "created_at": "2026-01-15T09:00:00Z",
      "updated_at": "2026-02-01T14:30:00Z"
    }
  ],
  "meta": {
    "total": 42,
    "page": 1,
    "per_page": 10,
    "total_pages": 5
  }
}

Status Codes

Code Description
200 Success
401 Missing or invalid token
422 Invalid query parameter

## Documenting Request Bodies

For `POST` and `PUT` endpoints, document the request body schema:

```markdown
### POST /api/documents

Creates a new document.

**Request Body** (`application/json`)

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `title` | string | ✅ | Document title (max 255 chars) |
| `content` | string | ✅ | Markdown content |
| `is_public` | boolean | ❌ | Public visibility. Default: `false` |
| `tags` | string[] | ❌ | Array of tag strings |

Documenting Errors

Create a central error reference so readers don’t have to hunt:

markdown
## Error Reference

All errors follow this format:

```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Human-readable description",
    "details": [
      { "field": "title", "issue": "must not be empty" }
    ]
  }
}
HTTP Code Error Code Description
400 VALIDATION_ERROR Request body failed validation
401 UNAUTHORIZED Token missing or expired
403 FORBIDDEN Token valid but lacks permission
404 NOT_FOUND Resource does not exist
429 RATE_LIMITED Too many requests
500 INTERNAL_ERROR Server error — contact support

## Multi-Language Code Examples

Provide examples in multiple languages. Tabbed examples help readers find their language quickly. A table of short snippets also works:

```markdown
**cURL**
```bash
curl -X POST https://api.example.com/api/documents \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"title": "My Doc", "content": "# Hello"}'

Python

python
import requests

response = requests.post(
    "https://api.example.com/api/documents",
    headers={"Authorization": f"Bearer {token}"},
    json={"title": "My Doc", "content": "# Hello"}
)
print(response.json())

JavaScript

javascript
const response = await fetch('https://api.example.com/api/documents', {
    method: 'POST',
    headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ title: 'My Doc', content: '# Hello' }),
});
const data = await response.json();

## Keeping API Docs Current

The most common problem with API documentation is drift — the docs say one thing and the API does another. Solutions:

- **Generate docs from code** — use tools like OpenAPI/Swagger or TypeDoc to auto-generate from annotations
- **Test your examples** — run curl examples as part of your CI to detect when they break
- **Version your docs** — keep separate documentation for each major API version
- **Add a changelog** — document every change in a `## Changelog` section so integrators know what changed