Back to Blog
API DocumentationOpenAPIDeveloper ExperienceBest Practices

API Documentation Best Practices That Developers Love

Create API documentation that helps developers succeed. From OpenAPI specs to interactive docs to code examples.

B
Bootspring Team
Engineering
September 12, 2024
5 min read

Great API documentation reduces support burden and increases adoption. Here's how to create docs that developers actually want to read.

Documentation Structure#

Essential Sections#

11. Getting Started 2 - Quick start guide 3 - Authentication setup 4 - First API call 5 62. Authentication 7 - How to get API keys 8 - Token management 9 - Security best practices 10 113. API Reference 12 - All endpoints 13 - Request/response examples 14 - Error codes 15 164. Guides & Tutorials 17 - Common use cases 18 - Step-by-step workflows 19 - Best practices 20 215. SDKs & Libraries 22 - Official libraries 23 - Code examples 24 - Community resources 25 266. Changelog 27 - Version history 28 - Breaking changes 29 - Migration guides

OpenAPI Specification#

Complete Example#

1openapi: 3.0.0 2info: 3 title: E-commerce API 4 version: 1.0.0 5 description: | 6 API for managing products, orders, and customers. 7 8 ## Authentication 9 All endpoints require a Bearer token in the Authorization header. 10 11 ## Rate Limits 12 - 100 requests per minute for free tier 13 - 1000 requests per minute for paid plans 14 15servers: 16 - url: https://api.example.com/v1 17 description: Production 18 - url: https://api.staging.example.com/v1 19 description: Staging 20 21paths: 22 /products: 23 get: 24 summary: List products 25 description: Retrieve a paginated list of products 26 tags: 27 - Products 28 parameters: 29 - name: page 30 in: query 31 description: Page number (1-indexed) 32 schema: 33 type: integer 34 default: 1 35 minimum: 1 36 - name: limit 37 in: query 38 description: Items per page 39 schema: 40 type: integer 41 default: 20 42 minimum: 1 43 maximum: 100 44 - name: category 45 in: query 46 description: Filter by category 47 schema: 48 type: string 49 responses: 50 '200': 51 description: Successful response 52 content: 53 application/json: 54 schema: 55 $ref: '#/components/schemas/ProductList' 56 example: 57 data: 58 - id: "prod_123" 59 name: "Widget" 60 price: 29.99 61 pagination: 62 page: 1 63 totalPages: 10 64 '401': 65 $ref: '#/components/responses/Unauthorized' 66 67 post: 68 summary: Create product 69 description: Create a new product 70 tags: 71 - Products 72 requestBody: 73 required: true 74 content: 75 application/json: 76 schema: 77 $ref: '#/components/schemas/CreateProduct' 78 example: 79 name: "New Widget" 80 price: 39.99 81 category: "electronics" 82 responses: 83 '201': 84 description: Product created 85 content: 86 application/json: 87 schema: 88 $ref: '#/components/schemas/Product' 89 '400': 90 $ref: '#/components/responses/BadRequest' 91 '401': 92 $ref: '#/components/responses/Unauthorized' 93 94components: 95 schemas: 96 Product: 97 type: object 98 properties: 99 id: 100 type: string 101 example: "prod_123" 102 name: 103 type: string 104 example: "Widget" 105 price: 106 type: number 107 format: float 108 example: 29.99 109 category: 110 type: string 111 example: "electronics" 112 createdAt: 113 type: string 114 format: date-time 115 required: 116 - id 117 - name 118 - price 119 120 CreateProduct: 121 type: object 122 properties: 123 name: 124 type: string 125 minLength: 1 126 maxLength: 255 127 price: 128 type: number 129 minimum: 0 130 category: 131 type: string 132 required: 133 - name 134 - price 135 136 Error: 137 type: object 138 properties: 139 error: 140 type: object 141 properties: 142 code: 143 type: string 144 message: 145 type: string 146 details: 147 type: array 148 items: 149 type: object 150 151 responses: 152 Unauthorized: 153 description: Authentication required 154 content: 155 application/json: 156 schema: 157 $ref: '#/components/schemas/Error' 158 example: 159 error: 160 code: "UNAUTHORIZED" 161 message: "Invalid or missing API key" 162 163 BadRequest: 164 description: Invalid request 165 content: 166 application/json: 167 schema: 168 $ref: '#/components/schemas/Error' 169 example: 170 error: 171 code: "VALIDATION_ERROR" 172 message: "Validation failed" 173 details: 174 - field: "name" 175 message: "Name is required" 176 177 securitySchemes: 178 bearerAuth: 179 type: http 180 scheme: bearer 181 bearerFormat: JWT 182 183security: 184 - bearerAuth: []

Code Examples#

Multiple Languages#

1## Create a Product 2 3<tabs> 4<tab title="cURL"> 5```bash 6curl -X POST https://api.example.com/v1/products \ 7 -H "Authorization: Bearer YOUR_API_KEY" \ 8 -H "Content-Type: application/json" \ 9 -d '{ 10 "name": "Widget", 11 "price": 29.99, 12 "category": "electronics" 13 }'
</tab> <tab title="JavaScript"> ```javascript const response = await fetch('https://api.example.com/v1/products', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'Widget', price: 29.99, category: 'electronics', }), });

const product = await response.json();

</tab> <tab title="Python"> ```python import requests response = requests.post( 'https://api.example.com/v1/products', headers={'Authorization': f'Bearer {api_key}'}, json={ 'name': 'Widget', 'price': 29.99, 'category': 'electronics', } ) product = response.json()
</tab> </tabs> ```

Error Documentation#

1## Error Codes 2 3| Code | Status | Description | 4|------|--------|-------------| 5| `VALIDATION_ERROR` | 400 | Request validation failed | 6| `UNAUTHORIZED` | 401 | Invalid or missing API key | 7| `FORBIDDEN` | 403 | Insufficient permissions | 8| `NOT_FOUND` | 404 | Resource not found | 9| `RATE_LIMITED` | 429 | Too many requests | 10| `INTERNAL_ERROR` | 500 | Server error | 11 12### Error Response Format 13 14All errors follow this format: 15 16```json 17{ 18 "error": { 19 "code": "VALIDATION_ERROR", 20 "message": "Validation failed", 21 "details": [ 22 { 23 "field": "email", 24 "message": "Invalid email format" 25 } 26 ] 27 } 28}

Handling Errors#

1try { 2 const response = await api.createProduct(data); 3} catch (error) { 4 if (error.code === 'VALIDATION_ERROR') { 5 // Show validation errors to user 6 error.details.forEach(d => console.error(`${d.field}: ${d.message}`)); 7 } else if (error.code === 'RATE_LIMITED') { 8 // Wait and retry 9 await sleep(error.retryAfter * 1000); 10 return createProduct(data); 11 } else { 12 // Log and show generic error 13 console.error('API error:', error); 14 } 15}
## Interactive Documentation ### Swagger UI / Redoc ```typescript // Express setup for Swagger UI import swaggerUi from 'swagger-ui-express'; import YAML from 'yamljs'; const swaggerDoc = YAML.load('./openapi.yaml'); app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerDoc, { customSiteTitle: 'My API Docs', customCss: '.swagger-ui .topbar { display: none }', })); // Redoc alternative app.get('/docs', (req, res) => { res.send(` <!DOCTYPE html> <html> <head> <title>API Documentation</title> <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet"> <style>body { margin: 0; padding: 0; }</style> </head> <body> <redoc spec-url='/openapi.yaml'></redoc> <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script> </body> </html> `); });

Best Practices#

1## Writing Style 2 3✅ Do: 4- Use clear, concise language 5- Provide complete, runnable examples 6- Document all error cases 7- Include authentication in every example 8- Show both request and response 9 10❌ Don't: 11- Use jargon without explanation 12- Show partial or broken examples 13- Assume prior knowledge 14- Hide important parameters 15- Forget to update after changes

Conclusion#

Great API documentation is an investment that pays off in developer adoption and reduced support burden. Start with OpenAPI, add code examples in multiple languages, and keep everything up to date.

Remember: developers judge your API by its documentation. Make it excellent.

Share this article

Help spread the word about Bootspring