Here's what most founders get wrong about APIs:
They think it's just endpoints.
"Just create /users and /orders and we're done."
Two months later, integrators are confused. Documentation is incomplete. Errors are cryptic. Versioning doesn't exist.
Smart startups? They design APIs like products—with developers as their customers.
This guide shows you how to design RESTful APIs that developers actually want to integrate.
REST vs GraphQL: What to Choose
Let's start with this foundational decision.
Choose REST If:
- You're building public API for unknown developers
- You want simplicity and familiarity
- HTTP caching matters (CDN, browser caching)
- You have standard CRUD operations
- Your team is more familiar with REST
Choose GraphQL If:
- You have complex data relationships
- Clients need exactly what they want (no over/under-fetching)
- Mobile clients have limited bandwidth
- You're building internal API with known clients
- Your team is experienced with GraphQL
Startup Reality: For most MVPs, start with REST. Add GraphQL later if specific needs emerge.
RESTful Design: The Basics
Good REST APIs follow principles consistently.
Resource-Based URLs
Good (Resource-Based):
plaintextGET /users # List usersGET /users/123 # Get specific userPOST /users # Create userPUT /users/123 # Update userDELETE /users/123 # Delete user
Bad (Action-Based):
plaintextGET /getAllUsersPOST /createNewUserPUT /updateUser/123DELETE /deleteUser/123
Key Principle: Use nouns (resources), not verbs (actions).
HTTP Methods: Use Correctly
Error Code | Status | Description |
|---|---|---|
VALIDATION_ERROR | 400 | Invalid input, validation fails |
FORBIDDEN | 403 | Insufficient permissions |
NOT_FOUND | 404 | Resource doesn't exist |
CONFLICT | 409 | Duplicate resource, conflict |
RATE_LIMIT_EXCEEDED | 429 | Too many requests |
INTERNAL_ERROR | 500 | Unexpected server error |
SERVICE_UNAVAILABLE | 503 | Service temporarily down |
Request Validation: Fail Fast
Validate at the gate. Don't let bad data through.
Input Validation Checklist
Validate:
- Required fields present
- Field types correct (string, number, boolean)
- Field values within constraints (min/max, length)
- Email addresses valid format
- URLs valid format
- Dates valid and in reasonable range
- Enum values match allowed options
- Array lengths within limits
Validation Example (Express)
javascriptimport { body, validationResult } from "express-validator";const userValidationRules = [body("email").isEmail().normalizeEmail().withMessage("Email is invalid"),body("firstName").trim().notEmpty().withMessage("First name is required").isLength({ min: 2, max: 50 }).withMessage("First name must be 2-50 characters"),body("role").isIn(["user", "admin", "moderator"]).withMessage("Invalid role"),];// In route handlerconst errors = validationResult(req);if (!errors.isEmpty()) {return res.status(400).json({error: {code: "VALIDATION_ERROR",message: "Invalid input",details: errors.array(),},});}
Pagination: Handle Large Datasets
Never return all records. Always paginate.
Pagination Approaches
1. Offset/Limit (Simple)
plaintextGET /users?limit=20&offset=0 # First 20GET /users?limit=20&offset=20 # Next 20GET /users?limit=20&offset=40 # Next 20
Pros: Simple, familiar Cons: Slow for large offsets, duplicates if data changes
2. Cursor-Based (Recommended)
plaintextGET /users?limit=20
json{"data": [...],"pagination": {"nextCursor": "eyJpIjoxNzg0fQ","hasMore": true}}
plaintextGET /users?limit=20&cursor=eyJpIjoxNzg0fQ
Pros:
- Consistent pagination even if data changes
- No performance degradation at large offsets
- Can paginate through real-time updates
Cons: More complex implementation
Startup Recommendation: Start with offset/limit for MVP. Implement cursor-based if scale requires.
Rate Limiting: Protect Your API
Without rate limiting, your API is vulnerable.
Rate Limiting Strategies
1. Fixed Window (Simple)
- X requests per minute/hour
- Example: 100 requests/minute
- Pros: Simple, easy to understand
- Cons: Bursts allowed at window reset
2. Sliding Window (Better)
- X requests in last Y minutes
- Example: 100 requests in last 60 seconds
- Pros: Prevents bursts
- Cons: More complex
3. Token Bucket (Most Flexible)
- Tokens refil at constant rate
- Burst capacity available
- Pros: Flexible, allows reasonable bursts
- Cons: Most complex
Rate Limit Response
httpHTTP/1.1 429 Too Many RequestsX-RateLimit-Limit: 100X-RateLimit-Remaining: 0X-RateLimit-Reset: 1642728000Retry-After: 60
json{"error": {"code": "RATE_LIMIT_EXCEEDED","message": "Rate limit exceeded. Try again in 60 seconds.","retryAfter": 60}}
Authentication: Secure from Day One
Never build custom auth. Use proven solutions.
Authentication Options
1. API Keys (Simplest)
plaintextAuthorization: Bearer sk_live_abc123xyz
Best For:
- Server-to-server integrations
- Internal tools
- Quick MVP authentication
Not For:
- User-facing apps (too easy to steal)
2. JWT (JSON Web Tokens)
plaintextAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Best For:
- Mobile apps
- Single-page applications
- Web apps with user accounts
Pros:
- Stateless (no server session storage)
- Can include claims (roles, permissions)
- Cross-domain
3. OAuth2 (Industry Standard)
plaintextAuthorization: Bearer access_token_from_oauth
Best For:
- Third-party integrations
- Social login (Google, GitHub)
- Enterprise SSO
Startup Recommendation: Use JWT for your main app. Add OAuth2 if third-party integrations needed.
API Documentation: Critical for Adoption
Without good documentation, developers won't integrate.
Essential Documentation Sections
1. Overview & Getting Started
- What does your API do?
- How to get API key?
- Quick start guide (5-minute example)
- Authentication methods
2. Endpoints
- Every endpoint documented
- Method (GET/POST/etc.)
- URL path
- Request parameters (query, body, headers)
- Response format
- Error responses
- Example requests/responses
3. Error Codes
- List of all error codes
- When each occurs
- How to fix
- Example scenarios
4. Rate Limiting
- Limits per plan/endpoint
- How limits reset
- How to request increase
5. Webhooks (if applicable)
- Event types
- Payload formats
- Retry logic
- Security (signatures)
Documentation Tools
OpenAPI/Swagger (Recommended):
yamlopenapi: 3.0.0info:title: My APIversion: 1.0.0paths:/users:get:summary: List usersresponses:"200":description: Successful responsecontent:application/json:schema:type: arrayitems:$ref: "#/components/schemas/User"
Tools:
- Swagger UI: Generate interactive docs from OpenAPI
- Redoc: Beautiful, responsive docs
- Stoplight: OpenAPI design and mocking
Alternative:
- ReadMe.io: Hosted API documentation platform
- Postman: Interactive documentation and testing
- GitBook: Custom documentation
Startup Recommendation: Use OpenAPI + Swagger UI for free, self-hosted docs.
API Monitoring: See What's Happening
You can't improve what you don't measure.
Metrics to Track
Performance Metrics:
- Response times (p50, p95, p99)
- Error rates by endpoint
- Request volume over time
- Slowest endpoints
Usage Metrics:
- Top endpoints by requests
- Top users/integrations by API calls
- Rate limit hits
- Failed requests by type
Business Metrics:
- Active API keys
- New integrations per week
- Churn of integrations
- Revenue by API tier
Monitoring Tools
APM (Application Performance Monitoring):
- Datadog: Full-stack monitoring
- New Relic: APM and infrastructure
- Sentry: Error tracking and performance
API-Specific:
- Postman: API monitoring and testing
- Moosoft: API performance monitoring
- Runscope: API testing and monitoring
Open Source:
- Prometheus + Grafana: Metrics visualization
- Elastic APM: Open-source APM
- Jaeger: Distributed tracing
API Design Checklist
Use this before launching your API.
Design:
- RESTful principles followed
- Resource-based URLs
- Correct HTTP methods used
- Appropriate status codes
- Versioning strategy defined
Security:
- Authentication implemented (JWT/OAuth2)
- Rate limiting configured
- Input validation on all endpoints
- SQL injection prevention
- XSS prevention
- HTTPS enforced
Documentation:
- Getting started guide
- All endpoints documented
- Request/response examples
- Error codes documented
- Authentication instructions
- Rate limiting documented
Monitoring:
- Error tracking configured
- Performance monitoring active
- Usage metrics tracked
- Alerting set up
Testing:
- Unit tests written
- Integration tests written
- Load testing completed
- Manual testing performed
Common API Mistakes
1. Returning Internal Errors
Bad:
json{"error": "SQL syntax error near 'WHERE'"}
Good:
json{"error": {"code": "INTERNAL_ERROR","message": "An unexpected error occurred"}}
2. Inconsistent Response Formats
Bad: Some endpoints return {data: [...]}, others return {items: [...]}
Good: Consistent format across all endpoints.
3. No Pagination
Bad: GET /users returns 10,000 users
Good: GET /users?limit=20&offset=0 returns 20 users with pagination info.
4. Missing Versioning
Bad: Change existing endpoint behavior, break all clients
Good: Create /api/v2/users, deprecate /api/v1/users with notice.
5. Poor Documentation
Bad: One page with raw endpoint list, no examples
Good: Interactive docs with examples, error codes, and quick start guide.
Related Reading
If you found this helpful, you might also enjoy:
- Building APIs with Node.js - Backend development
- Architecture Decision Records - Making architectural decisions
- Database Design for Startups - Backend data design
- Performance Optimization - API performance tips
Need Help Designing Your API?
At Startupbricks, we've designed APIs that developers love. We know what makes integrations easy and what frustrates developers.
Whether you need:
- Full API design and documentation
- Backend API implementation
- API testing and monitoring
- Integration support and examples
Let's talk about building API developers actually want to use.
Ready to design right? Download our free API Design Checklist and start today.
