Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Design a RESTful web API by making its public contract reflect the concepts clients need, then using HTTP methods, representations, status codes, and headers consistently. Start with the domain—not database tables or a list of actions—and decide how clients identify resources, change them, handle collections, and recover from errors. These are practical REST-oriented design conventions; JSON and plural URL paths alone do not make an API fully RESTful.

What “RESTful” means for an HTTP API

An HTTP request targets a resource, ordinarily identified by a URI. The service transfers a representation of that resource, while the HTTP method communicates the intended interaction and the response communicates its outcome through a status code and metadata. RFC 9110 describes HTTP as a uniform interface for interacting with resources by sending messages that manipulate or transfer representations. Microsoft Learn’s Azure Architecture Center describes a RESTful web API as one that uses REST architectural principles to achieve a stateless, loosely coupled interface between client and service.

In practice, teams often use “REST API” for an HTTP API that follows resource-oriented conventions, even when it does not implement every REST constraint. Be precise about that distinction: a JSON API with GET, POST, PUT, and DELETE routes may be REST-oriented without being fully RESTful. Evaluate whether the contract fits its clients and uses HTTP semantics accurately, rather than treating the label as a quality score.

Step 1: Model the domain contract before choosing routes

List the concepts clients need to see and the relationships among them. A public resource should represent a useful domain concept, not automatically mirror a database table, ORM object, or internal service. Internal storage can change without requiring every client to rewrite its integration; that separation is one of the main reasons to treat the API as a contract.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a hypothetical screenshot service, clients might work with screenshot requests and the resulting captures. The public contract could expose a screenshot request as a resource with an identifier, requested URL, status, and—when complete—a result reference. This is only an example of resource modeling; it does not describe ScreenshotNeo’s internal design.

  • Identify the actors and client tasks the API must support.
  • Name the domain concepts clients need to address independently.
  • Represent relationships deliberately, such as a project containing multiple screenshot requests.
  • Keep internal-only fields and implementation details out of the public representation unless clients have a real use for them.
  • Record assumptions and compatibility commitments before implementation begins.

Two useful tests: could a client understand the resource without knowing your storage schema, and could your team replace that schema without changing the client contract? If not, revise the model before settling the routes.

Step 2: Choose stable, understandable resource URIs

Use URI patterns that make collections and individual resources easy to distinguish. For example, a hypothetical API might use /v1/projects/{projectId}/screenshots for a collection and /v1/projects/{projectId}/screenshots/{screenshotId} for one screenshot request. The identifiers should remain stable for the resource’s lifetime and should not expose a database layout clients have no reason to depend on.

Prefer resource names and let the HTTP method express the operation where that fits. A route such as /screenshots/{id}/delete turns an ordinary resource interaction into an action-shaped URL; use an action endpoint only when the domain operation genuinely cannot be expressed clearly as a resource interaction. Naming conventions such as plural collection nouns are practical consistency choices, not a universal rule imposed by HTTP.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Nested paths can show an important relationship, but avoid encoding every association into a very deep URI. If clients need to address a screenshot independently, a stable top-level URI or a link to its canonical URI may be clearer than requiring every request to reproduce its parent path.

Step 3: Define method behavior using HTTP semantics

For each resource, write down what every supported method means, what it changes, and what response a client should expect. Standard method semantics matter: clients and intermediaries rely on properties such as safety and idempotence when deciding whether and how to retry, cache, or otherwise handle requests. Consult RFC 9110 when defining behavior rather than assigning familiar verbs private meanings.

Method Typical resource-oriented use Contract questions to settle
GET Retrieve a resource or collection representation. What filters, pagination controls, and response representation are supported? Does retrieval leave the resource unchanged?
POST Submit data to a collection, commonly to create a resource or initiate work. Does the response identify the created or accepted work? Can a client safely retry after a timeout, and how should duplicate submissions be handled?
PUT Replace a resource at a known target URI when that is the intended contract. Is the replacement behavior clear, including omitted fields? Is repeating the same request expected to have the same intended effect?
DELETE Request removal of a resource. What does a repeated delete mean? Is removal immediate, or does the response describe an asynchronous process?

This table is a design aid, not a substitute for the standard. Do not use GET for an operation that changes server state, or choose a method only because its name seems convenient. Specify behavior for retries, duplicate requests, and concurrent updates when those cases matter to clients.

Step 4: Specify representations, status codes, and errors

A route is not a complete API contract. Define the accepted request media type, request fields, response media type and shape, relevant headers, and status codes for success and failure. A client should be able to tell from the response whether its request succeeded, what resource or result it received, and what it can do next.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
REST API Design Rulebook
  • Used Book in Good Condition

For example, a synchronous creation request might return a representation of the created resource and an identifier clients can use later. If the service accepts work that is not complete yet, the response should make that distinction explicit rather than presenting acceptance as successful completion. Microsoft’s API implementation guidance emphasizes accurate status codes and headers and a response body clients can parse.

  • Document which fields are required, optional, read-only, or omitted when unknown.
  • Keep success and error representations consistent across endpoints.
  • Give validation errors enough structure for clients to locate the problem without exposing internal stack traces or implementation details.
  • Use status codes to communicate the outcome, and use response metadata where it helps clients interpret or follow up on that outcome.
  • Decide how the API handles unsupported media types, invalid input, missing resources, and conflicting updates; do not let each route invent a different convention.

For the hypothetical screenshot resource, a completed representation might contain an ID, requested URL, completion state, and result location. A failed request should distinguish a client input problem from a service-side or upstream failure when the contract can do so. Never tell clients a capture succeeded merely because the service accepted a request.

Step 5: Design collections and long-running work

Filtering and pagination

Collections can grow beyond what is sensible to return in one response. Decide which filters clients need, what ordering is stable, how pagination works, and what metadata or navigation helps them request the next page. Document limits and behavior at collection boundaries so clients do not have to infer them from occasional responses. Microsoft’s REST-oriented design guidance discusses filtering, pagination, and partial responses as explicit design concerns.

Choose partial responses only when they solve a real payload or client-fit problem. If clients can request only selected fields, define how that interacts with defaults and linked resources. Avoid an ambiguous query interface in which parameter names or combinations vary unpredictably by endpoint.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Asynchronous operations

For work that may outlast a normal request, separate “accepted” from “finished.” Define what the initial response says, how clients learn the operation or result URI, how they discover progress or completion, and how failures are represented. A client should not need to guess whether to poll, wait for a callback, or repeat the original request. Microsoft’s guidance covers asynchronous methods alongside pagination and related resource navigation.

Hypermedia links can help clients discover related resources and next actions when the API contract is designed to use them. If you include links, make their meaning and stability part of the contract; a decorative link field that clients must ignore does not by itself provide useful navigation.

Step 6: Plan evolution and document compatibility

API evolution is an intentional contract decision, not a side effect of changing a backing store. Decide how you will add optional fields, change behavior, deprecate old behavior, and communicate incompatible changes. Versioning can help when a breaking change is necessary, but a version number cannot compensate for unclear compatibility policy. Microsoft’s API design guidance also stresses versioning and differing client needs.

Document the contract so a developer can construct a valid request, understand every response and error, and assess compatibility before deploying an integration. Include resource definitions, methods, parameters, request and response examples, headers, status codes, pagination behavior, and the lifecycle of asynchronous work. Google Cloud’s API design guide is another reference, covering both REST and RPC design with particular attention to gRPC and HTTP mapping.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check the design against the actual range of clients. A mobile client, browser-based application, and backend service may have different payload or interaction needs. Where those needs conflict, make the trade-off explicit instead of exposing internal implementation details or multiplying special-case endpoints without a clear contract.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Use REST maturity levels as a teaching aid, not a score

The Richardson maturity model is commonly presented in four levels: Level 0 uses one URI and POST for operations; Level 1 gives resources separate URIs; Level 2 uses HTTP methods for operations; Level 3 adds hypermedia. The sequence helps explain how resource identification, method semantics, and discoverable links relate to REST-oriented design.

It is not a complete API quality metric. A 2021 Delphi study confronted eight Web API experts with a catalog of 82 design rules; its reported finding was that rules associated with Level 2 were considered critical, while reaching Level 3 was considered less important. That is the result of that study and its participants, not a universal consensus or evidence that hypermedia has no value. Assess an API against its client needs and contract, not only its maturity label.

A practical design review before implementation

  • Resource model: Do the public resources reflect domain concepts and relationships rather than database accidents?
  • URI stability: Can clients identify collections and individual resources without relying on private implementation details?
  • HTTP behavior: Does each method follow its standardized semantics, including expectations relevant to retries and caching?
  • Representations: Are media types, fields, headers, and error shapes specified consistently?
  • Collections and jobs: Are filtering, pagination, partial responses, and long-running work addressed where needed?
  • Evolution: Are compatibility expectations, deprecation, and any versioning approach documented?
  • Client usability: Can a consumer construct requests, interpret outcomes, and navigate related resources using the published documentation?

When comparing two plausible designs, weigh their fidelity to HTTP semantics, clarity of resource relationships, client discovery, compatibility cost, payload fit, and operational behavior for errors, pagination, and long-running requests. This is more useful than optimizing for a tidy URL pattern alone.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If your API design work is really about getting website screenshots rather than implementing browser capture yourself, ScreenshotNeo provides a website screenshot API and MCP server. Its one-call GET request returns an image or PDF; cookie banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before capture, with each step configurable. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing outcome. An MCP server exposes screenshot tools to Claude, Cursor, and other MCP clients.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation for request options and response details. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan. Sign up for 1,000 free screenshots a month, with no card required.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.