API Design: OpenAPI, Errors & Best Practices
Error Response Format
Consistent error responses make APIs easier to consume. Use RFC 7807 (Problem Details) or a similar structure.
// RFC 7807 Problem Details (recommended)
{
"type": "https://api.example.com/errors/validation",
"title": "Validation Failed",
"status": 422,
"detail": "The request body contains invalid data",
"instance": "/users/create",
"errors": [
{ "field": "email", "message": "Must be a valid email address" },
{ "field": "password", "message": "Must be at least 8 characters" }
],
"traceId": "abc123def456"
}
// Simpler format (also common)
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [...],
"requestId": "req_abc123"
}
}OpenAPI 3.1 Specification
openapi: 3.1.0
info:
title: My API
version: 1.0.0
paths:
/users/{id}:
get:
summary: Get user by ID
operationId: getUserById
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: User found
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: User not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
User:
type: object
required: [id, email]
properties:
id:
type: string
format: uuid
email:
type: string
format: email
name:
type: string
nullable: true
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWTRequest & Response Design
Use camelCase for JSON fields (standard in JS ecosystem); snake_case is common in Python/Ruby APIs
Always return the created/updated resource in POST/PUT/PATCH responses — avoids extra GET request
Envelope vs. bare: return bare object for single resource, envelope { data, meta } for collections
Nullable vs. omitted: be explicit — undefined fields can cause confusion. Either always include or document which fields may be absent.
Dates: use ISO 8601 strings ("2026-05-07T14:30:00Z") — not Unix timestamps in JSON
IDs: use strings (UUIDs or opaque IDs) not integers — avoids enumeration attacks and handles large IDs
Partial responses: ?fields=id,name,email reduces payload for mobile clients
API Design Checklist
Resources are nouns, HTTP methods are verbs — no /getUser or /deletePost
Consistent naming: plural nouns (/users not /user), consistent casing
Proper status codes: 201 for create, 204 for delete, 422 for validation errors
Pagination on all list endpoints — never return unbounded lists
Rate limiting on all public endpoints — document limits in headers
Authentication documented: which endpoints require auth, what format
Error responses are consistent and include a requestId for debugging
Breaking changes get a new version — document deprecation timeline
OpenAPI spec is generated from code (not hand-written) — single source of truth
CORS configured for browser clients — explicit origins, not wildcard for authenticated APIs
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free