RESTful API

Fundamentals Security Notes Jan 9, 2026 JAVASCRIPT
architecture rest api-design http best-practices

Definition

A RESTful API is a web service that fully implements the REST (Representational State Transfer) architectural style. While many APIs claim to be “REST APIs,” a truly RESTful API adheres to all six REST constraints: client-server separation, statelessness, cacheability, layered system, uniform interface, and optionally code-on-demand.

The key difference between a “REST API” and a “RESTful API” is completeness. Many APIs use HTTP and JSON and call themselves REST, but they might violate statelessness by maintaining server-side sessions, or they might ignore HATEOAS (hypermedia as the engine of application state). A RESTful API follows all the principles rigorously, making it truly scalable, maintainable, and self-descriptive.

The Richardson Maturity Model is often used to measure how RESTful an API is, with levels from 0 (the swamp of POX - Plain Old XML) to 3 (the glory of REST with full hypermedia controls). A genuinely RESTful API reaches level 3.

Example

GitHub API v3: GitHub’s REST API is a well-known example of a RESTful API. It uses resources (/repos, /users, /issues), proper HTTP methods (GET to read, POST to create, PATCH to update, DELETE to remove), includes hypermedia links in responses (navigation URLs), implements caching with ETags, and maintains statelessness - every request contains all necessary information.

Stripe API: Stripe’s payment API is highly RESTful. Creating a charge is POST /v1/charges, retrieving it is GET /v1/charges/:id, and refunding is POST /v1/refunds. Responses include hypermedia links like "url": "/v1/charges/ch_xxx" for related resources. It’s stateless, uses idempotent keys for safe retries, and leverages HTTP status codes correctly.

Twilio API: When you send an SMS via Twilio, you POST to /2010-04-01/Accounts/{AccountSid}/Messages.json. The response includes URLs to related resources like media attachments and message logs. Every request includes authentication credentials (stateless), and responses use proper HTTP status codes (201 for created, 400 for bad request).

Shopify Admin API: Shopify’s API for managing stores is RESTful: GET /admin/api/2024-01/products.json lists products, POST /admin/api/2024-01/products.json creates one, PUT /admin/api/2024-01/products/{id}.json updates it. Responses include pagination links and resource relationships, making the API self-navigable.

Analogy

The Self-Service Restaurant: A RESTful API is like a well-designed self-service restaurant. The menu (API documentation) tells you what’s available. Each counter is a resource (salad bar, grill, drinks). You don’t need to remember what you ordered before (stateless) - you just go to the counter and get what you want. Each counter has clear signs (uniform interface) telling you how to interact with it. The checkout (response) gives you a receipt with QR codes linking to nutrition info and allergen warnings (hypermedia links) so you can discover related information without asking.

The Library with Perfect Signage: A RESTful API is like a library where every book has a unique barcode (resource identifier), every section has clear signs (uniform interface), and checkout cards include “if you liked this, see also” recommendations (hypermedia). You don’t need a librarian to hold your hand - the system is self-descriptive. Whether you visited yesterday or never before (stateless), you can navigate it easily.

The Highway System: Think of a RESTful API as a modern highway system. Each exit has a unique number (resource ID), signs are standardized across the country (uniform interface), you don’t need to register with the highway authority for each trip (stateless), and each exit has signs pointing to related destinations (hypermedia). You can enter the system from anywhere and navigate using just the signs.

Code Example

// A genuinely RESTful API response includes hypermedia links
// Example: GitHub-style repository response

// GET /api/repos/facebook/react
{
  "id": 10270250,
  "name": "react",
  "full_name": "facebook/react",
  "description": "A JavaScript library for building user interfaces",
  "url": "https://api.github.com/repos/facebook/react",
  "html_url": "https://github.com/facebook/react",

  // Hypermedia links (HATEOAS) - discoverable navigation
  "forks_url": "https://api.github.com/repos/facebook/react/forks",
  "keys_url": "https://api.github.com/repos/facebook/react/keys{/key_id}",
  "collaborators_url": "https://api.github.com/repos/facebook/react/collaborators{/collaborator}",
  "issues_url": "https://api.github.com/repos/facebook/react/issues{/number}",
  "pulls_url": "https://api.github.com/repos/facebook/react/pulls{/number}",
  "milestones_url": "https://api.github.com/repos/facebook/react/milestones{/number}",

  // State is represented, not stored server-side
  "stargazers_count": 212000,
  "watchers_count": 212000,
  "language": "JavaScript",
  "has_issues": true,
  "has_projects": true,

  // Cache control for scalability
  "updated_at": "2026-01-09T10:30:00Z"
}

// Response headers demonstrate RESTful principles
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=60, s-maxage=60
ETag: "686897696a7c876b7e"
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
Link: <https://api.github.com/repos/facebook/react/commits>; rel="commits"

// Subsequent request with caching (stateless)
GET /api/repos/facebook/react
If-None-Match: "686897696a7c876b7e"

// Server responds with 304 Not Modified if unchanged
HTTP/1.1 304 Not Modified
Cache-Control: max-age=60

Diagram

graph TB
    subgraph "RESTful API Constraints"
        CS[Client-Server
Separation] SL[Stateless
Communication] CA[Cacheable
Responses] LS[Layered
System] UI[Uniform
Interface] COD[Code-on-Demand
(Optional)] end subgraph "Uniform Interface Constraints" RI[Resource
Identification] RM[Resource Manipulation
via Representations] SM[Self-Descriptive
Messages] HM[Hypermedia as
Engine of State] end UI --> RI UI --> RM UI --> SM UI --> HM subgraph "Richardson Maturity Model" L0[Level 0
The Swamp of POX] L1[Level 1
Resources] L2[Level 2
HTTP Verbs] L3[Level 3
Hypermedia Controls] L0 -->|Introduce Resources| L1 L1 -->|HTTP Methods + Status Codes| L2 L2 -->|HATEOAS| L3 end L3 -.->|Fully RESTful| CS

Security Notes

SECURITY NOTES

CRITICAL: RESTful APIs use HTTP methods and resources. Security comes from proper implementation.

REST Constraints:

  • Client-server: Separation of concerns
  • Stateless: Each request self-contained
  • Cacheable: Responses indicate if cacheable
  • Uniform interface: Consistent design
  • Layered system: Can add intermediaries
  • Code on demand: Optional, rarely used

Security Principles:

  • Use HTTPS: Always encrypt communication
  • Authenticate: Require authentication
  • Authorize: Verify permissions
  • Validate input: Sanitize all input
  • Rate limit: Prevent abuse
  • Log: Audit trail for compliance

HTTP Method Safety:

  • GET: Safe, idempotent, cacheable
  • POST: Unsafe, non-idempotent, idempotency key
  • PUT: Unsafe, idempotent, idempotency key
  • DELETE: Unsafe, idempotent
  • PATCH: Unsafe, non-idempotent

Error Handling:

  • Standard codes: Use correct HTTP status codes
  • Error responses: Consistent error format
  • No internal details: Don’t expose server internals
  • Helpful messages: Provide actionable error messages

Best Practices

  1. Reach Richardson Level 3: Implement full hypermedia with links in responses
  2. Design resource-oriented URLs: Use nouns (/users/123/orders) not verbs (/getUserOrders?id=123)
  3. Use HTTP methods correctly: GET for read, POST for create, PUT/PATCH for update, DELETE for remove
  4. Return proper status codes: 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error
  5. Implement caching: Use ETags, Last-Modified, Cache-Control headers to reduce load
  6. Support content negotiation: Accept multiple formats via Accept header (JSON, XML, etc.)
  7. Include pagination for collections: Use limit, offset, or cursor-based pagination with links to next, prev
  8. Version your API: Use URI versioning (/v1/) or Accept header versioning
  9. Provide comprehensive documentation: Use OpenAPI/Swagger to describe your API
  10. Implement HATEOAS: Include navigational links so clients can discover resources dynamically

Common Mistakes

Stateful sessions: Storing user state on the server violates statelessness. Use tokens (JWT, OAuth) that carry all necessary context.

Missing hypermedia: Returning data without links makes the API less discoverable. Clients shouldn’t need to construct URLs manually.

Incorrect HTTP methods: Using GET for operations that modify state, or POST for everything, breaks the uniform interface.

Poor status codes: Returning 200 OK for all responses (even errors) makes debugging harder and violates REST principles.

Ignoring caching: Not setting Cache-Control, ETag, or Last-Modified headers wastes bandwidth and server resources.

Verbs in URLs: Paths like /getUser or /createOrder are RPC-style, not RESTful. Use /users/:id with appropriate HTTP methods.

Tight coupling: Forcing clients to know the exact URL structure instead of following hypermedia links creates brittle integrations.

Breaking changes without versioning: Changing response schemas without API versioning breaks existing clients.

Standards & RFCs