Cheat Sheet
Naming Conventions
- General Rules
- Use nouns for resources:
/users,/products - Use camelCase or snake_case for fields:
firstName,user_id
- Use nouns for resources:
- Endpoints
- Retrieve all:
GET /resources - Retrieve one:
GET /resources/{id} - Create:
POST /resources - Update:
PUT /resources/{id}orPATCH /resources/{id} - Delete:
DELETE /resources/{id}
- Retrieve all:
- Custom Actions
- Use verbs for actions on resources
POST /resources/{id}/activatePOST /resources/{id}/reset-password
- Use verbs for actions on resources
Filtering & Pagination
-
Filtering
- Use query parameters for filtering:
GET /users?status=active&role=admin
- Use consistent syntax for multiple filters:
GET /products?category=electronics&price[lt]=100
- Use query parameters for filtering:
-
Pagination
- Use
pageSizeandpageTokenfor cursor-based pagination:GET /users?pageSize=10&pageToken=abc123
- Include pagination metadata in th response:
{ "data": [...], "pagination": { "nextPageToken": "xyz456", "totalCount": 100 } }
- Use
API Versioning
- Versioning Strategies
- URL-based: Include version in the URL
/v1/resources
- Header-based: Use headers to specify versions
Accept: application/vnd.api+json;version=2
- URL-based: Include version in the URL
- Best Practices
- Maintain backward compatibility as much as possible
- Deprecate old versions with clear timelines
- Document breaking changes thoroughly
Error Handling
-
Standard HTTP Status Codes
- 200: Successful request
- 201: Resource created
- 204: No Content
- 400: Bad Request
- 401: Authentication failed
- 403: No permission
- 404: Resource not found
- 500: Server-side issue
-
Error Response Structure
{ "error": { "code": 400, "message": "Invalid request payload", "details": [ { "field": "email", "message": "Email is required" }, { "field": "password", "message": "Password must be at least 8 characters" } ] } }
Security Measures
- Authentication
- Use OAuth 2.0 or OpenID Connect for secure authentication
- Include
Bearer <token>in theAuthorizationheader
- Rete Limiting
- Implement limits to prevent abuse
- Use
X-RateLimit-Limit,X-RateLimit-Remaining, andX-RateLimit-ResetheadersX-RateLimit-Limit: 1000,X-RateLimit-Remaining: 500
- Data Protection
- Use HTTPS for all requests to encrypt data
- Validate all inputs to prevent injection attacks
- Error Messages
- Avoid exposing sensitive information in error responses
- Bad:
Database connection failed: Invalid password - Good:
500 Internal Server Error
- Bad:
- Avoid exposing sensitive information in error responses
Naming Conventions
Naming conventions are critical in API design as they directly impact the clarity, usability, and consistency of the API. A well-designed naming system makes the API intuitive and easy to adopt for developers, minimizing learning curves and errors.
Core Principles
- Consistency
- Maintain uniform patterns across the API to reduce cognitive load.
- Follow a single case style (e.g.,
camelCase,snake_case) and apply it universally to field names, query parameters, and endpoints.
- Expressiveness
- Names should convey clear meaning about the resource or action they represent.
- Use self-explanaory terms; avoid ambiguous or generic names.
- Predictability
- Naming should align with standard conventions and developer expectations.
- CRUD operations should map to GET, POST, PUT, DELETE in a predictable manner.
- Simplicity
- Avoid verbose or redundant terms in resource and parameter names.
- Keep paths short and meaningful.
Best Practices
- Resources
- Use Nouns: Represent resources with nouns, not verbs, as the resource represents an entity or collection.
- Good:
/users,/orders - Bad:
/getUsers,/createOrder
- Good:
- Use plural nouns to represent collections and singular nouns for individual items.
- Collection:
GET /users - Single resource:
GET /users/{id}
- Collection:
- Hierarchical Relationships: Use path hierarchy to indicate relationships between resources.
- Articles for a user:
GET /users/{id}/articles - Comments for an article:
GET /users/{id}/articles/{article_id}/comments
- Articles for a user:
- Use Nouns: Represent resources with nouns, not verbs, as the resource represents an entity or collection.
- Actions
- Use Http Methods Appropriately: Let HTTP methods define actions instead of embedding them in resource names.
- Good:
GET /users→ Retrieve a list of usersPOST /users→ Create a new user
- Bad:
/users/getAll,/users/add
- Good:
- Custom Actions: For operations beyond CRUD, append actions to resource paths as sub-resources. Use verbs for clarity.
- Example:
- Activate user:
POST /users/{id}/activate - Reset password:
POST /users/{id}/reset-password
- Activate user:
- Example:
- Use Http Methods Appropriately: Let HTTP methods define actions instead of embedding them in resource names.
- Query Parameters
- Use Descriptive Parameter Names: Query parameters should clearly describe the filtering or sorting applied.
GET /products?category=electronicss&price[lt]=100
- Avoid Embedding Parameters in URLs: Parameters should not be part of the path; use query strings instead.
- Good:
/users?status=active - Bad:
/users/status/active
- Good:
- Use Descriptive Parameter Names: Query parameters should clearly describe the filtering or sorting applied.
- Case Conventions
- camelCase: Commom use in JSON and JavaScript APIs for names
- snake_case: Often used in RESTful APIs, especially for query parameters
- Consistently apply the chosen convention throughout the API.
- Avoid Redundancy
- Do not repeat resource names unnecessarily.
- Good:
/users/{id} - Bad:
/users/user/{id}
- Good:
- Do not repeat resource names unnecessarily.
Common Pitfalls to Avoid
- Inconsistent Naming Styles
- Mixing
camelCase, andsnake_case, andPascalCaseleads to confusion.
- Mixing
- Overly Verbose Names
- Avoid long and redundant names.
- Example:
- Good:
/users/{id} - Bad:
/fetchUserDetailsById/{id}
- Good:
- Ambiguous or Non-Descriptive Names
- Avoid names like
/dataor/infothat don't clearly describe the resource.
- Avoid names like
- Embedding HTTP Methods in Names
- Avoid paths like
/users/getAllor/orders/delete/{id}
- Avoid paths like
Real-World Example
A well-structured API for managing blog posts might look like this:
| Operation | Endpoint | HTTP Method |
|---|---|---|
| List all posts | /posts | GET |
| Retrieve a single post | /posts/{id} | GET |
| Create a new post | /posts | POST |
| Update a post | /posts/{id} | PUT or PATCH |
| Delete a post | /posts/{id} | DELETE |
| List comments on a post | /posts/{id}/comments | GET |
| Add a comment to a post | /posts/{id}/comments | POST |
| Like a post | /posts/{id}/like | POST |
Filtering & Pagination
Filtering and pagination are crucial for APIs that handle large datasets. They allow clients to retrieve only the data they need, improving performance and reducing bandwidth usage. Properly designed filtering and pagination make APIs more efficient, scalable, and user-friendly.
Filtering
Purpose
Filtering enables clients to refine their data requests by specifying conditions. It reduces the size of responses by returning only the relevant data.
Best Practices
- Use Query Parameters
- Define filters as query parameters in the URL.
- Example:
GET /users?status=active
- Example:
- Define filters as query parameters in the URL.
- Support Multiple Filters
- Allow combining filters to refine results further.
- Example:
GET /products?category=electronics&price[lt]=100
- Example:
- Allow combining filters to refine results further.
- Use Standard Operators
- Support common operators for comparison, such as:
eq(equals):/users?age[eq]=30lt(less than):/products?price[lt]=100gt(greater than):/products?price[gt]=50in(in list):/users?role[in]=admin,editor
- Support common operators for comparison, such as:
- Ensure Consistent Syntax
- Follow a consistent convention for naming and structuring filters.
- Document Available Filters
- Clearly specify all supported filters in the API documentation.
- Secure Filtering
- Validate and sanitize filter inputs to prevent SQL injection or other security risks.
Pagination
Purpose
Pagination splits large datasets into smaller, manageable chunks, allowing clients to retrieve data incrementally.
Types of Pagination
- Offset-Based Pagination
- Uses
offsetandlimitquery parametersGET /users?offset=10&limit=20
- Advantages: Simple to implement and widely supported.
- Disadvantages: Inefficient for large datasets due to database scanning.
- Uses
- Cursor-Based Pagination
- Uses a
pageTokenorcursorfor navigating through data.GET /users?pageSize=10&pageToken=abc123
- Advantages: More efficient for large datasets.
- Disadvantages: Slightly more complex to implement.
- Uses a
- Keyset Pagination
- Relies on sorted unique keys (e.g.,
id) to retrieve data incrementally- GET /users?lastSeenId=50&limit=20
- Advantages: Highly performant for real-time data retrieval.
- Relies on sorted unique keys (e.g.,
Best Practices
- Return Pagination Metadata
- Include metadata like nextPageToken, totalCount, and pageSize in the response.
{ "data": [...], "pagination": { "nextPageToken": "xyz456", "totalCount": 500, "pageSize": 20 } }
- Include metadata like nextPageToken, totalCount, and pageSize in the response.
- Provide Flexible Parameters
- Allow clients to specify
pageSize(number of items per page)- Default: Provide a sensible default (e.g.,
20). - Limit: Enforce a maximum (e.g.,
100) to prevent excessive data loads.
- Default: Provide a sensible default (e.g.,
- Allow clients to specify
- Use Stable Sorting
- Ensure consistent results by sorting data by unique keys (e.g.,
id)
- Ensure consistent results by sorting data by unique keys (e.g.,
- Handle Empty Pages Gracefully
- Return an empty data array when no resulrs exist:
{ "data": [], "pagination": { "nextPageToken": null, "totalCount": 0, "pageSize": 20 } }
- Return an empty data array when no resulrs exist:
- Optimize Backend Queries
- Use database indexes for faster filtering and pagination.
- Document Pagination Parameters
- Clearly explain the supported pagination methods in the API documentation.
Common Pitfalls
- Relying Solely on Offset-Based Pagination
- Causes performance issues for large datasets.
- Prefer cursor-based or keyset pagination for scalability.
- Lack of Pagination Metadata
- Failing to include
nextPageTokenortotalCountmakes client-side navigation difficult.
- Failing to include
- Ignoring Security
- Unsanitized filters can lead to injection attacks. Always validate inputs.
- Inconsistent Syntax
- Mixing pagination and filtering conventions confuses users. Ensure clarity and consistency.
API Versioning
API versioning is the practice of managing changes to an API over time. It allows developers to introduce new features or modify existing functionality without disrupting existing clients. Proper versioning ensures stability, backward compatibility, and a smooth transition to updated APIs.
Why API Versioning Matters
- Backward Compatibility: Ensure existing clients can continue to use the API without breaking their implementations.
- Controlled Changes: Enable developers to introduce new features, deprecate old ones, or fix issues without immediate impact.
- Flexibility: Allow consumers to adopt updates at their own pace.
- Transparency: Clearly communicate changes and versions to API consumers.
Versioning Strategies
- URL-Based Versioning:
- Include version in the URL
/v1/resources- Pros:
- Easy to understand and implement.
- Explicit versioning in the API path.
- Cons:
- URL structure changes with each version.
- Not ideal for fine-grained versioning of resources or methods.
- Header-Based Versioning:
- Description: The version is specified in HTTP headers.
-
GET /users Accept: application/vnd.api+json;version=2 - Pros:
- Cleaner URLs without version clutter.
- Supports fine-grained versioning (e.g., resource-level versions).
- Cons:
- Requires consumers to configure headers explicity.
- Less discoverable compared to URL-based versioning.
- Query Parameter Versioning
- Description: The version is passed as a query parameter.
GET /users?version=2- Pros:
- Easy to implement.
- Compatible with dynamic routing systems.
- Cons:
- Adds complexity to the query string.
- Can make debugging more challenging.
- Content-Based Versioning
- Description: The version is embedded in the request body.
-
{ "version": "2", "data": { "id": 123, "name": "John" } } - Pros:
- Flexible for APIs with non-HTTP transport layers.
- Cons:
- Versioning logic is tightly coupled to the payload.
- Harder to implement and enforce consistently.
- Semantic Versioning
- Description: Versions are expressed as
MAJOR.MINOR.PATCH. - Example:
GET /users(Header:X-API-Version: 1.2.3)
- Pros:
- Provides detailed information about backward compatibility.
- Allows non-breaking changes in minor/patch updates.
- Cons:
- Requires clear documentation to differentiate breaking vs. non-breaking changes.
- Description: Versions are expressed as
Best Practices
- Start with Version 1
- Use
v1as the starting point, even if it's the first release.
- Use
- Maintain Backward Compatibility
- Avoid breaking changes within the same version.
- Introduce breaking changes only in major versions (e.g.,
v2).
- Deprecate Old Versions Gracefully
- Announce deprecations well in advance.
- Provide clear timelines for decommissioning old versions.
- Document All Versions
- Clearly document what each version supports and any differences between versions.
- Use Clear and Predictable Semantics
- Follow conventions that are easy for consumers to understand and adopt.
- Communicate Changes Transparently
- Provide changelogs or migration guides to help consumers transition between versions.
When to introduce a New Version
- Breaking Changes: Modifying or removing existing functionality.
- Example: Renaming fields, removing endpoints.
- Significant New Features: Introducing major new capabilities.
- Example: Adding support for a new data format.
- Incompatible Enhancements: Changes that cannot coexist with older versions.
- Example: Changing authentication mechanisms.
Common Pitfalls
- Skipping Versioning Initially
- Adding versioning later can lead to inconsistencies and technical debt.
- Overloading Versions with Breaking Changes
- Avoid introducing multiple breaking changes in a single update.
- Unclear Deprecation Timelines
- Consumers may not migrate if deprecations are not clearly communicated.
- Lack of Migration Support
- Provide tools or documentation to help clients transition between versions.
Error Handling
Error handling is critical for building user-friendly and reliable APIs. A well-structured error-handling strategy helps API consumers diagnose and fix issues efficiently while maintaining security and clarity.
Goals of Error Handling
- Clarity: Errors should provide enough information for users to understand what went wrong.
- Consistency: Use a standardized format for error responses across the API.
- Security: Avoid exposing sensitive internal details in error messages.
- Actionability: Enable consumers to take corrective actions based on the error response.
Best Practices for Error Handling
Use Standard HTTP Status Codes
HTTP status codes should reflect the nature of the error:
- 2xx - Success
200 OK: The request was successful.201 Created: A resource was created successfully.
- 4xx - Client Errors
400 Bad Request: The request is malformed or contains invalid data.401 Unauthorized: Authentication is required or failed.403 Forbidden: The client does not have permission.404 Not Found: The resource does not exist.409 Conflict: There is a conflict with the current state of the resource.
- 5xx - Server Errors
500 Internal Server Error: A generic server-side issue.503 Service Unavailable: The server is temporarily unavailable.
Provide a Consistent Error Response Format
Error responses should follow a predictable and standardized structure:
{
"error": {
"code": 400,
"message": "Invalid request payload",
"details": [
{
"field": "email",
"message": "Email is required"
},
{
"field": "password",
"message": "Password must be at least 8 characters"
}
]
}
}
- Fields in the Error Response:
code: The HTTP status code of the error.message: A human-readable description of the error.details: (Optional) An array of specific issues for granular feedback.
Differentiate Between Client and Server Errors
- Client errors (
4xx) should indicate that the problem lies with the request. - Server errors (
5xx) should indicate that the issue is on the server-side.
Avoid Exposing Internal Details
- Do Not: Leak stack traces, database errors, or sensitive configurations.
- Do: Use generic messages like
"An internal error occurred. Please try again later."
Include Error Codes for Machine Parsing
- Use error codes for programmatic identification and handling.
{ "error": { "code": 400, "errorCode": "INVALID_INPUT", "message": "The 'email' field is required." } }
Common Scenarios and How to Handle Them
Validation Errors
- Use Case: Invalid input data.
- HTTP Code:
400 Bad Request - Response:
{ "error": { "code": 400, "message": "Invalid input data", "details": [ { "field": "email", "message": "Email is required" }, { "field": "password", "message": "Password is too short" } ] } }
Authentication Errors
- Use Case: Missing or invalid authentication credentials.
- HTTP Code:
401 Unauthorizedfor authentication issues.403 Forbiddenfor permission issues.
- Response:
{ "error": { "code": 401, "message": "Authentication failed. Token is invalid or expired." } }
Resource Not Found
- Use Case: The requested resource does not exist.
- HTTP Code:
404 Not Found - Response:
{ "error": { "code": 404, "message": "Resource not found: User with ID 123 does not exist." } }
Conflict Errors
- Use Case: State conflicts, such as duplicate data or resource locking.
- HTTP Code:
409 Conflict - Response:
{ "error": { "code": 409, "message": "A user with this email address already exists." } }
Rate Limiting
- Use Case: Too many requests from a client.
- HTTP Code:
429 Too Many Requests - Response:
{ "error": { "code": 429, "message": "Too many requests. Please try again later." } }
Internal Server Errors
- Use Case: Unexpected issues on the server.
- HTTP Code:
500 Internal Server Error - Response:
{ "error": { "code": 500, "message": "An internal server error occurred. Please contact support." } }
Advanced Error Handling Techniques
Error Localization
- Include localized messages for multi-language support.
{ "error": { "code": 400, "message": "Invalid input data", "localizedMessage": { "en": "Invalid input data", "es": "Datos de entrada no válidos" } } }
Correlation IDs
- Include a unique identifier for debugging server-side errors
{ "error": { "code": 500, "message": "An internal server error occurred.", "correlationId": "1234567890" } }
Error Logging and Monitoring
- Log errors with detailed context for debugging.
- Use monitoring tools like Sentry or Datadog to track error trends.
Common Pitfalls
- Generic Error Messages: Avoid vague messages like
"Something went wrong."Be specific and actionable. - Inconsistent Error Structures: Ensure all endpoints return errors in the same format.
- Overexposing Sensitive Data: Do not include internal stack traces, or database details in error messages.
Security Measures
Security is paramount in API design to protect sensitive data, ensure system integrity, and prevent abuse. A comprehensive security strategy addresses authentication, authorization, data protection, and abuse prevention.
Authentication
Authentication ensures that only authorized clients or users can access your API.
Best Practices:
- Use Secure Protocols
- Always use HTTPS to encrypt communication between the client and the API server.
- Token-Based Authentication
- Use
OAuth 2.0orOpenID Connectfor secure and scalable authentication. - Issue access tokens and refresh tokens to users.
- Use
- API Keys
- Issue unique API keys to identify and authenticate clients.
- Restrict API keys to specific IP addresses or endpoints.
- Session Management
- Use secure session tokens with short expiration times.
- Implement token rotation to minimize exposure in case of compromise.
Authorization
Authorization ensures that authenticated clients can only access resources they are allowed to.
Access Control Model
- Role-Based Access Control (RBAC)
- Assign roles to users and define permissions for each role.
- Example:
Admincan create, update, delete resources.Viewercan only read resources.
- Attribute-Based Access Control (ABAC)
- Use policies based on user attributes, resource properties, and environmental conditions.
- Least Privilege Principle
- Grant users the minimum permissions required for their role or action.
Data Protection
Data protection measures secure sensitive information during transmission and storage.
- Encryption
- Use TLS/SSL for all API communications.
- Encrypt sensitive data at rest (e.g., database encryption).
- Input Validation
- Validate and sanitize all input data to prevent injection attacks (e.g., SQL Injection, XSS).
- Use parameterized queries or prepared statements for database interactions.
- Output Escaping
- Escape data before displaying it to prevent Cross-Site Scripting (XSS) attacks.
- Mask Sensitive Data
- Avoid returning sensitive information in responses.
Rate Limiting and Throttling
Rate limiting prevents abuse by restricting the number of requests a client can make.
- Rate Limiting
- Define request limits per user, IP address, or API key.
- Example:
X-RateLimit-Limit: 1000,X-RateLimit-Remaining: 500
- Throttling
- Slow down clients that exceed rate limits instead of blocking them outright.
- Error Responses
- Return
429 Too Many Requestsfor rate limit violations.
- Return
Input and Output Validation
Input Validation
- Validate data types, ranges, and formats for all incoming data.
- Example: Ensure email fields contain valid email addresses.
Output Validation
- Ensure API responses conform to expected formats to prevent accidental data leaks.
Logging and Monitoring
Audit Logs
- Log critical API actions, such as user logins, data modifications, and permission changes.
- Store logs securely and ensure they cannot be tampered with.
Error Monitoring
- Use tools like Sentry or Datadog to track and analyze errors and security incidents.
Access Monitoring
- Monitor access patterns for unusual behavior (e.g., spikes in request volume).
Secure Error Handling
- Avoid Sensitive Information in Error Message
- Standardized Error Responses
- Return consistent error formats with minimal information.
API Gateway Security
- Use an API Gateway
- Act as a reverse proxy for API traffic.
- Implement authentication, rate limiting, and logging at the gateway level.
- IP Whitelisting
- Allow access only from trusted IP ranges.
Security Testing
- Regular Penetration Testing
- Conduct periodic tests to identify vulnerabilities.
- Automated Security Scanning
- Use tools like OWASP ZAP or Burp to identify common security flaws.
- API-Specific Security Checks
- Validate OpenAPI specifications for security compliance.
Common Pitfalls to Avoid
- Hardcoding Secrets
- Never store API keys, tokens, or passwords in code repositories.
- Exposing Too Much Data
- Use pagination, filtering, and field selection to limit response sizes.
- Weak Authentication
- Avoid simple or static authentication mechanisms.
- Ignoring CORS
- Configure Cross-Origin Resource Sharing (CORS) policies to restrict access from unauthorized origins.