An API (Application Programming Interface) is a contract that allows two software systems to communicate with each other. It defines:

  • How requests should be made
  • What data is expected
  • What responses will be returned

APIs abstract internal implementation and expose only what is necessary, enabling loose coupling between systems.

REST vs SOAP
Feature REST SOAP
Style Architectural style Strict protocol
Data format JSON (mostly) XML only
Transport HTTP mainly HTTP, SMTP, TCP
State Stateless Can be stateful
Performance Lightweight, fast Heavy, slow
Usage today Everywhere Mostly legacy systems

REST is preferred for modern applications due to simplicity and performance. SOAP is used in enterprise legacy systems.

An API is RESTful only if it adheres to REST constraints.

REST Architectural Constraints
1. Client–Server Architecture
  • Client handles UI and user experience
  • Server handles data and business logic
  • Both evolve independently
2. Statelessness
  • Server does not store client session state
  • Each request is self-contained
3. Cacheability
  • Responses specify cache rules
  • Improves performance and scalability
4. Uniform Interface

This is the most critical constraint.

Statelessness means that the server does not retain any information about the client's previous requests.

Each request must contain:
  • Authentication details
  • Required parameters
  • Contextual data
Benefits:
  • Easy horizontal scaling
  • Fault tolerance
  • Reduced server memory usage

Common Misconception:

Using JWT does **not** make the server stateful. The state is stored on the client.

REST
  • Resource-oriented
  • URLs represent entities
  • HTTP semantics are meaningful

Example:

GET /orders/12
RPC (Remote Procedure Call)
  • Action-oriented
  • URLs represent operations
  • HTTP is used as a transport mechanism

Example:

POST /getOrder
REST
  • Multiple endpoints (one per resource)
  • Fixed response structure
  • Can lead to over-fetching or under-fetching
GraphQL
  • Single endpoint
  • Client specifies exactly what data it needs
  • Reduces over-fetching
When to use REST:
  • Simple CRUD operations
  • Well-defined resources
  • Easier caching
When to use GraphQL:
  • Complex data requirements
  • Multiple related entities
  • Mobile apps (reduce bandwidth)

HTTP methods define what action the client wants to perform on a resource. Correct usage is critical for clarity, scalability, caching, security, and correctness.

Difference Between GET, POST, PUT, PATCH, DELETE

Each HTTP method has a clear semantic meaning. Misusing them is a design flaw, not a style choice.

Method Purpose Creates Resource Modifies Resource Idempotent Safe
GET Retrieve data No No Yes Yes
POST Create / Trigger Yes Yes No No
PUT Replace resource Yes (if absent) Yes (full) Yes No
PATCH Partial update No Yes (partial) Not guaranteed No
DELETE Remove resource No Yes Yes No
Idempotency

An operation is idempotent if performing it multiple times results in the same system state.

Example

PUT /users/10

Multiple identical PUT requests result in the same resource state.

HTTP Methods and Idempotency
Method Idempotent Explanation
GET Yes Read-only
PUT Yes Full replacement
DELETE Yes Deletes once
HEAD Yes Metadata only
POST No Creates new resource
PUT (Full Replacement)
  • Replaces the entire resource
  • Missing fields are removed
  • Idempotent by definition
PUT /profile/5 { "name": "John", "age": 30 }

If address is omitted, it is deleted.

PATCH (Partial Update)
  • Updates only specified fields
  • Does not affect other fields
  • Not strictly idempotent
PATCH /profile/5 { "age": 31 }

Only the provided attributes change.

Why Both Exist?
Reason Explanation
Clarity PUT means replace, PATCH means modify
Safety PATCH avoids accidental data loss
Efficiency PATCH sends less data
Semantics Different intentions, different guarantees

Technically yes. Practically no.

Explanation
  • HTTP specification does not forbid GET request bodies
  • However:
    • Servers often ignore them
    • Proxies may drop them
    • Caching systems do not consider them
Best Practice
  • Use query parameters for GET
  • Use POST if request data is complex
❌ Bad: GET/search (bodycontains filters)
✅ Good: GET /search?name=alice&age=25
Use POST When:
  1. Server generates the resource ID
  2. Operation is non-idempotent
  3. Action is not a full replacement
  4. Triggering processing (emails, payments)
POST /orders

Server decides:

/orders/8743
PUT is Used When:
  • Client knows the resource URI
  • Entire resource state is provided
  • Idempotency is required
PUT /orders/8743
Safe Methods

A method is safe if it does not modify server state.

Safe methods:

  • GET
  • HEAD
  • OPTIONS

Even if called repeatedly, they only read data.

Idempotent Methods

A method is idempotent if performing it multiple times results in the same system state.

Idempotent methods:

  • GET
  • PUT
  • DELETE
  • HEAD
Key Difference
Concept Meaning
Safe No side effects
Idempotent Same result on repetition

A method can be:

  • Idempotent but not safe (DELETE)
  • Safe and idempotent (GET)
1. API Key

A simple secret string passed in requests to identify the caller.

How it works:
  • Server generates a unique key for each client
  • Client includes key in every request (header or query param)
  • Server validates the key
GET /api/users Authorization: Api-Key sk_live_12345...
Pros:
  • Simple to implement
  • Good for server-to-server communication
  • Easy to revoke
Cons:
  • No user identity (only identifies the app)
  • Hard to implement fine-grained permissions
  • Risk if leaked
Use Case:

Machine-to-machine communication, backend services, third-party API integrations.

2. OAuth 2.0

An authorization framework that allows third-party apps to access user resources without exposing credentials.

How it works:
  • User authorizes app to access their data
  • Authorization server issues an access token
  • App uses token to make API requests
  • Token has limited scope and expiration
Flow Example (Authorization Code):
  1. App redirects user to authorization server
  2. User logs in and grants permission
  3. Server redirects back with authorization code
  4. App exchanges code for access token
  5. App uses token to access protected resources
Pros:
  • User doesn't share password with third-party apps
  • Fine-grained permissions (scopes)
  • Tokens can be revoked without changing password
  • Supports refresh tokens for long-lived access
Cons:
  • Complex to implement
  • Requires multiple round trips
  • Token storage and management overhead
Use Case:

Third-party integrations (e.g., "Sign in with Google"), delegated access, social logins.

3. JWT (JSON Web Token)

A compact, self-contained token format for securely transmitting information between parties.

Structure:
header.payload.signature Example: eyJhbGc...header .eyJzdWI...payload (user data, expiry) .SflKxw...signature (verification)
How it works:
  • Server creates JWT with user info and signs it
  • Client stores JWT (localStorage, cookie)
  • Client sends JWT with each request
  • Server verifies signature and extracts data
GET /api/profile Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Pros:
  • Stateless (no server-side storage needed)
  • Self-contained (includes user info)
  • Works across multiple servers
  • Easy to scale
Cons:
  • Cannot be revoked before expiration
  • Larger than session IDs
  • Sensitive data in payload is visible (base64 encoded, not encrypted)
Use Case:

Single Sign-On (SSO), microservices authentication, mobile apps, stateless APIs.

Comparison Table
Feature API Key OAuth JWT
Complexity Simple Complex Moderate
User Identity No Yes Yes
Stateless No No Yes
Revocation Easy Easy Hard
Best For Server-to-server Third-party access Stateless APIs

Tokens should be sent in the Authorization header using the Bearer scheme.

✅ Recommended:
GET /api/users Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Why Authorization Header?
  • Secure: Not logged in URLs or browser history
  • Standard: Industry convention (RFC 6750)
  • Clean: Separates auth from business logic
  • CORS-friendly: Works with cross-origin requests
❌ Avoid:
1. Query Parameters
GET /api/users?token=abc123 // BAD

Problems:

  • Logged in server logs
  • Visible in browser history
  • Can be leaked via Referer header
2. Request Body (for GET requests)
GET /api/users { "token": "abc123" } // BAD

Problems:

  • GET requests shouldn't have a body
  • Breaks HTTP semantics
  • Caching issues
3. Cookies (for APIs)

Cookies work for browser-based sessions but are problematic for APIs:

  • CSRF vulnerability
  • Not ideal for mobile/desktop apps
  • Same-origin limitations
Exception: Web Applications

For traditional web apps, HttpOnly cookies are acceptable and can be more secure:

  • Protected from XSS attacks
  • Automatically sent by browser
  • Require CSRF protection
Access Token

A short-lived token used to access protected resources.

Characteristics:
  • Short lifespan: 15 minutes to 1 hour
  • Sent with every request
  • Contains user permissions/claims
  • Cannot be easily revoked (before expiry)
Refresh Token

A long-lived token used to obtain new access tokens without re-authentication.

Characteristics:
  • Long lifespan: Days to months
  • Used only to get new access tokens
  • Stored securely (database)
  • Can be revoked
Flow:
  1. User logs in → Server returns access token + refresh token
  2. Client uses access token for API requests
  3. Access token expires
  4. Client sends refresh token to get new access token
  5. Server validates refresh token and issues new access token
// Login Response { "access_token": "eyJhbGc...", // expires in 1 hour "refresh_token": "dGhpcyB...", // expires in 30 days "token_type": "Bearer", "expires_in": 3600 } // Refresh Request POST /auth/refresh { "refresh_token": "dGhpcyB..." } // New Access Token { "access_token": "newToken...", "expires_in": 3600 }
Why Use Both?
Benefit Explanation
Security Short-lived access tokens limit damage if leaked
User Experience Users don't need to re-login frequently
Revocation Refresh tokens can be revoked from database
Rotation Can implement refresh token rotation for added security
Best Practices:
  • Store refresh tokens securely (encrypted in DB)
  • Implement refresh token rotation
  • Set appropriate expiration times
  • Revoke refresh tokens on logout
  • Detect and handle refresh token reuse (security breach)
1. Authentication & Authorization
  • Use OAuth 2.0 or JWT for authentication
  • Implement role-based access control (RBAC)
  • Validate permissions on every request
2. HTTPS Only
  • Always use TLS/SSL encryption
  • Reject HTTP requests
  • Use HSTS headers
3. Input Validation
  • Validate all input data
  • Sanitize user inputs
  • Use parameterized queries (prevent SQL injection)
  • Limit request size
4. Rate Limiting
  • Prevent brute force attacks
  • Protect against DDoS
  • Use token bucket or sliding window algorithms
HTTP/1.1 429 Too Many Requests X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1640995200
5. API Keys & Secrets
  • Never hardcode secrets in code
  • Use environment variables
  • Rotate keys regularly
  • Store in secure vaults (AWS Secrets Manager, HashiCorp Vault)
6. CORS Configuration
  • Whitelist specific origins
  • Don't use wildcard (*) in production
  • Validate Origin header
7. Security Headers
  • Content-Security-Policy
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Strict-Transport-Security
8. Logging & Monitoring
  • Log all authentication attempts
  • Monitor for suspicious patterns
  • Set up alerts for anomalies
  • Never log sensitive data (passwords, tokens)
9. API Versioning
  • Version your APIs
  • Maintain backward compatibility
  • Deprecate old versions gracefully
10. Error Handling
  • Don't expose sensitive info in errors
  • Use generic error messages
  • Log detailed errors server-side

A replay attack occurs when an attacker intercepts a valid request and resends it to gain unauthorized access or repeat an action.

Prevention Strategies:
1. Timestamps

Include a timestamp in each request and reject requests older than a threshold (e.g., 5 minutes).

GET /api/payment Authorization: Bearer token... X-Timestamp: 1640995200

Server checks:

if (currentTime - requestTimestamp > 300 seconds) { return 401 Unauthorized; }
2. Nonce (Number Used Once)

A unique value for each request. Server tracks used nonces and rejects duplicates.

GET /api/payment Authorization: Bearer token... X-Nonce: 8f3b4e2a-9c1d-4a5b-8e6f-7d9c3a2b1e4f X-Timestamp: 1640995200

Server logic:

if (nonceExists(nonce)) { return 401 Unauthorized; // Replay detected! } storeNonce(nonce, expiryTime);
3. Request Signing

Create a signature using request data + timestamp + secret key. Server verifies signature.

// Client Side const signature = HMAC_SHA256( method + url + timestamp + body, secretKey ); // Request POST /api/payment X-Signature: abc123... X-Timestamp: 1640995200

Server verifies:

expectedSignature = HMAC_SHA256( method + url + timestamp + body, secretKey ); if (signature !== expectedSignature) { return 401 Unauthorized; }
4. Token Expiration
  • Use short-lived tokens (15-60 minutes)
  • Implement refresh token mechanism
  • Expired tokens cannot be replayed
5. HTTPS Only
  • Prevents interception of requests
  • TLS encryption protects data in transit
  • Essential for all other strategies to work
6. Idempotency Keys

For critical operations (payments, orders), use idempotency keys to ensure operations execute only once.

POST /api/payments Idempotency-Key: unique-key-123
Best Practice: Combine Multiple Strategies
  • HTTPS + Timestamp + Nonce + Short-lived tokens
  • Request signing for critical operations
  • Idempotency keys for financial transactions
Example: AWS API Request Signing

AWS uses a combination of:

  • Timestamp (X-Amz-Date header)
  • Request signing (Authorization header with signature)
  • Short-lived credentials

A payment system API must prioritize security, correctness, idempotency, and reliability. Performance is important, but correctness beats speed every time when money is involved.

Core Requirements
  • Secure authentication
  • Idempotent payment requests
  • Strong validation
  • Auditability
  • Failure and retry handling
Key Resources
  • customers
  • payments
  • transactions
  • refunds
API Endpoints
Create a Payment
POST /payments

Headers:

Authorization: Bearer <token> Idempotency-Key: <uuid>

Request Body:

{ "customer_id":"cust_123", "amount":5000, "currency":"INR", "payment_method":"card" }

Response:

{ "payment_id":"pay_456", "status":"processing" }
Payment Status
GET /payments/{payment_id}
Refund Payment
POST /payments/{payment_id}/refund
Critical Design Considerations
Idempotency
  • Prevents duplicate charges on retries
  • Mandatory for POST /payments
Asynchronous Processing
  • Payment gateways are slow and unreliable
  • Use webhooks for final confirmation
Security
  • HTTPS only
  • Token-based auth
  • Never expose internal transaction IDs

A social media feed must optimize for read performance, not writes. Writes are occasional. Reads are constant.

Core Requirements
  • Pagination
  • Sorting by time or relevance
  • Scalability
  • Caching
Key Resources
  • users
  • posts
  • feeds
  • likes
  • comments
API Endpoints
Create Post
POST /posts
Get User Feed
GET /feed?cursor=abc123&limit=20

Response:

{ "items":[ ...], "next_cursor":"def456" }
Pagination Strategy

Cursor-based pagination is preferred over offset-based.

Why:

  • Stable results
  • Better performance
  • No duplicate or missing posts
Feed Generation Approaches
Fan-out on Write
  • Push post IDs to followers
  • Faster reads
  • Higher write cost
Fan-out on Read
  • Generate feed dynamically
  • Slower reads
  • Lower storage cost

File upload APIs must handle large payloads, network failures, and resumability.

Simple Upload (Small Files)
POST /files Content-Type: multipart/form-data
Large File Upload
Step 1: Initiate Upload
POST /uploads

Response:

{ "upload_id":"upl_123" }
Step 2: Upload Chunks
PUT /uploads/{upload_id}/parts/{part_number}
Step 3: Complete Upload
POST /uploads/{upload_id}/complete
Design Considerations
  • Chunking
  • Retry failed chunks
  • Virus scanning
  • Size and type validation

Microservices APIs must be independent, loosely coupled, and resilient.

Core Principles
Service Ownership
  • Each service owns its data
  • No shared databases
API Contracts
  • Backward compatible
  • Versioned
Communication Patterns
  • REST for synchronous calls
  • Events for asynchronous communication
API Gateway Pattern
  • Authentication
  • Rate limiting
  • Routing
  • Aggregation
Failure Handling
  • Timeouts
  • Retries with backoff
  • Circuit breakers
Observability
  • Centralized logging
  • Metrics
  • Distributed tracing
1. Security First
  • Always use HTTPS
  • Implement proper authentication and authorization
  • Validate all inputs
  • Never expose sensitive internal IDs
2. Design for Reliability
  • Make operations idempotent where possible
  • Handle failures gracefully
  • Use appropriate status codes
  • Implement proper error responses
3. Optimize for Performance
  • Use caching strategically
  • Implement pagination for large datasets
  • Consider async operations for slow processes
  • Use appropriate HTTP methods
4. Plan for Scale
  • Version your APIs from the start
  • Design for backward compatibility
  • Implement rate limiting
  • Use API gateways for routing and aggregation
5. Maintain Observability
  • Log all requests and responses
  • Track metrics and performance
  • Implement distributed tracing
  • Monitor error rates and latency