9 min read • Guide 752 of 877
API Development Best Practices
APIs are contracts between systems. GitScrum helps teams plan, track, and deliver API work with proper documentation and testing.
API Planning
API Stories in GitScrum
API STORY STRUCTURE:
┌─────────────────────────────────────────────────────────────┐
│ API-123: Create User Endpoint │
├─────────────────────────────────────────────────────────────┤
│ │
│ As an API consumer │
│ I can create a new user via POST /api/v1/users │
│ So that I can onboard users programmatically │
│ │
│ ═══════════════════════════════════════════════════════════ │
│ │
│ ENDPOINT SPECIFICATION: │
│ │
│ Method: POST │
│ Path: /api/v1/users │
│ Auth: Bearer token required │
│ │
│ Request Body: │
│ { │
│ "email": "user@example.com", │
│ "name": "John Doe", │
│ "role": "member" │
│ } │
│ │
│ Success Response (201): │
│ { │
│ "id": "usr_abc123", │
│ "email": "user@example.com", │
│ "name": "John Doe", │
│ "role": "member", │
│ "created_at": "2024-01-15T10:30:00Z" │
│ } │
│ │
│ Error Responses: │
│ 400 - Invalid input (missing field, invalid format) │
│ 401 - Authentication required │
│ 403 - Insufficient permissions │
│ 409 - Email already exists │
│ │
│ ═══════════════════════════════════════════════════════════ │
│ │
│ ACCEPTANCE CRITERIA: │
│ ☐ Endpoint accepts valid user data │
│ ☐ Returns 201 with created user │
│ ☐ Validates email format │
│ ☐ Rejects duplicate emails (409) │
│ ☐ Requires authentication │
│ ☐ Documentation updated │
│ ☐ Tests cover happy path and errors │
└─────────────────────────────────────────────────────────────┘
API Design Checklist
API DESIGN PRINCIPLES:
┌─────────────────────────────────────────────────────────────┐
│ │
│ NAMING CONVENTIONS: │
│ │
│ ✅ Resources are nouns, plural: │
│ /users, /projects, /tasks │
│ │
│ ✅ Use kebab-case for multi-word: │
│ /project-members, /time-entries │
│ │
│ ✅ Nest for relationships: │
│ /projects/{id}/tasks │
│ /users/{id}/notifications │
│ │
│ ❌ Don't use verbs in path: │
│ /getUsers → GET /users │
│ /createProject → POST /projects │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ HTTP METHODS: │
│ │
│ GET - Retrieve resource(s) │
│ POST - Create new resource │
│ PUT - Replace entire resource │
│ PATCH - Update part of resource │
│ DELETE - Remove resource │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ STATUS CODES: │
│ │
│ 200 OK - Successful GET/PUT/PATCH │
│ 201 Created - Successful POST │
│ 204 No Content - Successful DELETE │
│ 400 Bad Request - Invalid input │
│ 401 Unauthorized - No auth │
│ 403 Forbidden - No permission │
│ 404 Not Found - Resource doesn't exist │
│ 409 Conflict - Duplicate/conflict │
│ 422 Unprocessable - Validation failed │
│ 500 Server Error - Our fault │
└─────────────────────────────────────────────────────────────┘
API Versioning
Version Strategy
API VERSIONING APPROACHES:
┌─────────────────────────────────────────────────────────────┐
│ │
│ OPTION 1: URL PATH (Recommended) │
│ │
│ /api/v1/users │
│ /api/v2/users │
│ │
│ Pros: Clear, easy to route, cacheable │
│ Cons: URL changes between versions │
│ │
│ OPTION 2: HEADER │
│ │
│ Accept: application/vnd.api.v1+json │
│ │
│ Pros: Clean URLs │
│ Cons: Less discoverable, harder to test │
│ │
│ OPTION 3: QUERY PARAMETER │
│ │
│ /api/users?version=1 │
│ │
│ Pros: Simple │
│ Cons: Can be cached incorrectly │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ VERSIONING RULES: │
│ │
│ MAJOR VERSION (v1 → v2): │
│ • Breaking changes │
│ • Removed endpoints │
│ • Changed response structure │
│ │
│ MINOR VERSION (tracked in changelog): │
│ • New endpoints │
│ • New optional fields │
│ • Non-breaking changes │
│ │
│ MAINTAIN MULTIPLE VERSIONS: │
│ v1: Deprecated, sunset date announced │
│ v2: Current stable version │
│ v3: Beta/preview (optional) │
└─────────────────────────────────────────────────────────────┘
Breaking Changes
MANAGING BREAKING CHANGES:
┌─────────────────────────────────────────────────────────────┐
│ │
│ WHAT'S A BREAKING CHANGE: │
│ │
│ ✅ BREAKING: │
│ • Removing an endpoint │
│ • Removing a field from response │
│ • Changing field type (string → object) │
│ • Changing required/optional status │
│ • Changing authentication method │
│ │
│ ✅ NOT BREAKING: │
│ • Adding new endpoint │
│ • Adding new field to response │
│ • Adding new optional parameter │
│ • Changing error message text │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ DEPRECATION PROCESS: │
│ │
│ 1. ANNOUNCE │
│ "v1 will be deprecated in 6 months" │
│ Add deprecation warnings to responses │
│ │
│ 2. SUPPORT TRANSITION │
│ Run v1 and v2 simultaneously │
│ Provide migration guide │
│ │
│ 3. MONITOR USAGE │
│ Track v1 API calls │
│ Notify active v1 consumers │
│ │
│ 4. SUNSET │
│ Final warning 30 days before │
│ Turn off v1, return 410 Gone │
│ │
│ GITSCRUM TRACKING: │
│ Label: breaking-change │
│ Include migration notes in story │
│ Link to affected integrations │
└─────────────────────────────────────────────────────────────┘
API Documentation
Documentation Standards
API DOCUMENTATION REQUIREMENTS:
┌─────────────────────────────────────────────────────────────┐
│ │
│ EVERY ENDPOINT NEEDS: │
│ │
│ 1. OVERVIEW │
│ What does this endpoint do? │
│ When would you use it? │
│ │
│ 2. REQUEST │
│ • Method and path │
│ • Headers required │
│ • Path parameters │
│ • Query parameters │
│ • Request body schema │
│ • Example request │
│ │
│ 3. RESPONSE │
│ • Success response schema │
│ • Example success response │
│ • All possible error responses │
│ • Example error responses │
│ │
│ 4. CODE EXAMPLES │
│ cURL, JavaScript, Python examples │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ DOCUMENTATION TOOLS: │
│ │
│ OpenAPI/Swagger: │
│ • Define API in YAML/JSON │
│ • Auto-generate docs │
│ • Interactive testing │
│ │
│ Keep docs with code: │
│ • /docs/api/ in repository │
│ • Updates with PRs │
│ • Version control │
│ │
│ DEFINITION OF DONE: │
│ ☐ Endpoint works │
│ ☐ Tests written │
│ ☐ Documentation updated │
│ ☐ Changelog entry added │
└─────────────────────────────────────────────────────────────┘
API Testing
Test Categories
API TESTING STRATEGY:
┌─────────────────────────────────────────────────────────────┐
│ │
│ UNIT TESTS: │
│ Test individual functions/handlers │
│ • Validation logic │
│ • Business logic │
│ • Data transformations │
│ │
│ INTEGRATION TESTS: │
│ Test endpoint behavior │
│ • Request → Response flow │
│ • Database interactions │
│ • External service calls (mocked) │
│ │
│ CONTRACT TESTS: │
│ Verify API matches specification │
│ • Response matches OpenAPI spec │
│ • Breaking changes caught │
│ │
│ E2E TESTS: │
│ Test full user workflows │
│ • Create user → Create project → Add task │
│ • Real database, real services │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ TEST COVERAGE FOR ENDPOINTS: │
│ │
│ ☐ Happy path (success case) │
│ ☐ Validation errors (400) │
│ ☐ Authentication required (401) │
│ ☐ Permission denied (403) │
│ ☐ Not found (404) │
│ ☐ Conflict/duplicate (409) │
│ ☐ Rate limiting (429) │
│ ☐ Edge cases (empty input, max values) │
│ │
│ ACCEPTANCE CRITERIA: │
│ Tests must cover all documented responses │
└─────────────────────────────────────────────────────────────┘
Error Handling
Consistent Errors
ERROR RESPONSE STANDARDS:
┌─────────────────────────────────────────────────────────────┐
│ │
│ ERROR RESPONSE STRUCTURE: │
│ │
│ { │
│ "error": { │
│ "code": "validation_error", │
│ "message": "Invalid input provided", │
│ "details": [ │
│ { │
│ "field": "email", │
│ "message": "Invalid email format" │
│ }, │
│ { │
│ "field": "name", │
│ "message": "Name is required" │
│ } │
│ ], │
│ "request_id": "req_abc123" │
│ } │
│ } │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ ERROR CODES (Machine-readable): │
│ │
│ validation_error - Invalid input │
│ authentication_error - No/invalid auth │
│ authorization_error - No permission │
│ not_found - Resource doesn't exist │
│ conflict - Duplicate/conflict │
│ rate_limited - Too many requests │
│ server_error - Internal error │
│ │
│ PRINCIPLES: │
│ │
│ • Machine-readable error codes │
│ • Human-readable messages │
│ • Field-level details when relevant │
│ • Request ID for debugging │
│ • Don't expose internal details │
│ • Consistent structure across all endpoints │
└─────────────────────────────────────────────────────────────┘