← All posts
7 min read

REST APIs: Resource-Oriented Interfaces Using HTTP Semantics

#technology#rest#api#http
📑 On this page

REST is frequently used to mean "an API that sends JSON over HTTP." The architectural idea is more specific.

A REST-like API models information as resources addressed by URLs and uses standard HTTP methods, representations, status semantics, and caching rules.

Not every practical HTTP API follows every formal REST constraint. The useful goal is a predictable interface that works with HTTP rather than hiding all behavior behind one generic call.

A concrete example: orders

GET /orders/42

requests a representation of order 42.

DELETE /orders/42

requests deletion according to the server's authorization and business rules.

The URL identifies the resource. The method communicates the operation.

This is clearer than:

POST /api
{ "action": "deleteOrder", "id": 42 }

Resources are concepts

A resource can be:

  • Customer
  • Order
  • Product
  • Invoice
  • Search result collection
  • Current session
  • Report generation job

A resource is not necessarily one database row or file.

/account-summary/1042 may combine several data sources.

Model resources around domain concepts clients understand, not storage implementation.

URLs identify resources

Common URL shapes include:

/orders
/orders/42
/customers/1042/orders

Use nouns for resources and let methods express general operations.

URLs should be stable and understandable.

Avoid deeply nested paths that require callers to know every internal ownership relationship.

A globally unique order may be reachable as /orders/42 even if it also appears in a customer's order collection.

Representations

A resource can have representations in JSON, XML, HTML, or another format.

Example JSON:

{
  "id": "42",
  "status": "paid",
  "total": {
    "amount": "75.00",
    "currency": "USD"
  }
}

The representation is not the resource itself.

The server may calculate fields, hide sensitive values, or include links.

Content negotiation can use headers such as Accept and Content-Type, though many APIs standardize on one format for simplicity.

GET reads without intended mutation

GET retrieves a representation.

It is safe in HTTP semantics: the caller does not request a state change.

Servers may still log, count, or cache the request as incidental effects, but a crawler or retry should not create an order.

GET responses can often be cached.

Do not place secrets or large sensitive payloads in URLs because paths and query strings may appear in logs, browser history, and intermediary systems.

POST creates or submits work

POST /orders may create an order:

POST /orders
Content-Type: application/json
 
{
  "cartId": "c-17",
  "shippingAddressId": "a-9"
}

A successful response might use:

201 Created
Location: /orders/42

POST is not inherently idempotent. Repeating it may create another resource.

Use idempotency keys when network retry could duplicate consequential work.

PUT replaces a known resource

PUT commonly means create or replace the representation at a known URL:

PUT /users/1042/preferences

Sending the same complete representation repeatedly should produce the same intended state.

That makes PUT idempotent in HTTP semantics.

Be clear whether omitted fields are removed, reset, or preserved. If the operation is partial rather than replacement, PATCH is often more expressive.

PATCH applies a partial change

PATCH updates part of a resource.

PATCH /orders/42
 
{
  "deliveryNote": "Leave with reception"
}

The API must define:

  • Patch document format
  • Null versus omission
  • Allowed fields
  • Conflict behavior
  • Validation

A patch can be idempotent, but is not automatically so.

For example, "increment quantity by one" changes again on every retry.

DELETE requests removal

DELETE /orders/42 requests deletion or domain-specific removal.

The server may:

  • Delete permanently
  • Mark inactive
  • Reject because records must be retained
  • Start an asynchronous deletion workflow

HTTP method semantics do not override business and legal constraints.

Document what deletion means and what subsequent GET requests return.

Repeated DELETE requests should normally converge on the resource being absent.

Stateless requests

REST includes a stateless constraint: each request contains the information necessary to understand it, rather than depending on hidden server conversation state.

Authentication can use a session identifier, but the request carries that identifier.

Statelessness supports:

  • Horizontal scaling
  • Intermediaries
  • Independent request handling

The application still has state in databases and resources.

Stateless requests do not mean a stateless business system.

HTTP status semantics

Useful codes include:

  • 200 OK
  • 201 Created
  • 204 No Content
  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 409 Conflict
  • 422 Unprocessable Content
  • 429 Too Many Requests
  • 500 Internal Server Error
  • 503 Service Unavailable

Choose codes consistently and add structured error details.

Do not return 200 with { "success": false } for every failure. That discards protocol semantics used by clients, caches, gateways, and monitoring.

Caching

HTTP supports caching through headers such as:

  • Cache-Control
  • ETag
  • Last-Modified
  • Vary

A product catalog response may be reusable briefly.

A private account response should prevent shared caching or vary safely by authorization.

Correct caching can reduce latency and load.

Incorrect caching can leak personalized data, so cache behavior belongs in API design.

Conditional requests

An ETag identifies a representation version.

For efficient reads:

If-None-Match: "order-42-v7"

The server can return 304 Not Modified.

For safe updates:

If-Match: "order-42-v7"

The server changes the resource only if the version still matches, preventing one client from silently overwriting another's update.

Conditional requests connect HTTP semantics to concurrency control.

Collections and filtering

GET /orders?status=unpaid&customerId=1042

can represent a filtered collection.

Define:

  • Supported filters
  • Sort order
  • Pagination
  • Maximum page size
  • Consistency

Avoid accepting arbitrary field or query expressions that expose internal schema and create unbounded database work.

Collection design must protect both usability and resource cost.

Representations can include links:

{
  "id": "42",
  "customer": "/customers/1042",
  "items": "/orders/42/items"
}

Links help clients discover related resources and reduce URL construction assumptions.

Formal REST emphasizes hypermedia as the engine of application state, though many real APIs use documented URL templates instead.

Even without full hypermedia, returning canonical resource URLs improves clarity.

Actions that do not fit CRUD

Business operations such as:

  • Cancel order
  • Capture payment
  • Approve refund
  • Rotate key

may not fit simple field updates.

Model an action as a resource or explicit subresource:

POST /orders/42/cancellations

This creates an auditable cancellation request.

Do not force every domain action into PATCH status when the transition has validation, identity, and side effects.

Asynchronous operations

Long work can return:

202 Accepted
Location: /report-jobs/r-77

The client polls the job resource or receives a webhook.

The job representation can expose:

  • Pending
  • Running
  • Succeeded
  • Failed
  • Output link

This is clearer than keeping one HTTP connection open indefinitely or pretending acceptance means completion.

Compatibility

Safer changes include:

  • Adding optional fields
  • Adding new resources
  • Adding new enum values when clients tolerate them

Breaking changes include:

  • Removing fields
  • Redefining meaning
  • Changing type
  • Tightening validation unexpectedly
  • Changing default ordering

Clients should ignore unknown response fields where appropriate.

Servers should version or migrate incompatible changes deliberately.

Knowledge check

  1. How is a resource different from a database row?
  2. Why should GET not create a business side effect?
  3. How do PUT and PATCH usually differ?
  4. What can If-Match prevent?
  5. Why might a cancellation be modeled as its own resource?

The one idea to remember

REST-like APIs use resource URLs and HTTP's existing methods, status, caching, and conditional semantics to create predictable contracts. Good design follows domain meaning rather than reducing every operation to generic CRUD.