Web Development

REST API Design Best Practices

- - 6 min read -rest api design, api best practices, http methods
REST API Design Best Practices

Related: How to Secure a Web Application

A good REST API feels obvious. A developer can guess the next endpoint, knows what each response means, and trusts that the same call gives the same result. A bad one needs constant guesswork and breaks clients without warning. The difference is not luck. It comes from a small set of clear rules. This guide walks through the practices that make a REST API clean, predictable, and safe to grow.

Key takeaways

  • Model your API around resources, which are nouns, and let HTTP methods be the verbs.
  • Use the right HTTP method and status code so clients understand the result without parsing text.
  • Plan versioning, pagination, and a single error format before you launch, not after.
  • Make unsafe operations idempotent where you can, so retries do not cause double charges or duplicate records.
  • Protect the API with auth and rate limiting, and tell clients clearly when they hit a limit.

Resources and nouns

The core idea of REST is to model your system as resources. A resource is a thing, so its name is a noun. A user, an order, an invoice. The URL points to the thing. The HTTP method says what you want to do with it. Do not put verbs in the URL. The method is already the verb.

GoalGoodAvoid
List ordersGET /ordersGET /getOrders
One orderGET /orders/42GET /order?id=42
Create orderPOST /ordersPOST /createOrder
Items in an orderGET /orders/42/itemsGET /orderItems?order=42

Use plural nouns for collections, so /orders not /order. Keep the nesting shallow. One level, like /orders/42/items, is fine. Deep chains get hard to read and maintain. Past one level, prefer a top level resource with a filter, such as /items?order=42.

HTTP methods and status codes

HTTP already gives you the verbs. Use each one for its job, and the API becomes self explaining. The method also tells clients whether a call is safe to retry.

  • GET reads data and changes nothing. Safe to repeat.
  • POST creates a new resource. Not safe to repeat as is.
  • PUT replaces a resource fully. Safe to repeat, the end state is the same.
  • PATCH updates part of a resource.
  • DELETE removes a resource. Safe to repeat, it stays gone.

Status codes are just as important. They let a client react without reading the body.

CodeMeaningUse when
200 OKSuccessA read or update worked
201 CreatedResource madeA POST created something
204 No ContentSuccess, no bodyA delete worked
400 Bad RequestBad inputThe request body is invalid
401 UnauthorizedNot logged inMissing or bad credentials
403 ForbiddenNot allowedLogged in but no permission
404 Not FoundNo such resourceThe id does not exist
409 ConflictState clashDuplicate or version conflict
429 Too Many RequestsRate limitedThe client sent too many calls
500 Server ErrorOur faultAn unexpected server error

The simple rule: 2xx means it worked, 4xx means the client made a mistake, and 5xx means the server made a mistake. Never return 200 with an error message inside.

Versioning, pagination, and errors

These three things are hard to add later, so decide them up front.

Versioning. Once people depend on your API, you cannot change it freely. Put a version in the path, like /v1/orders. When you must make a breaking change, ship /v2 and keep /v1 alive for a while.

Pagination. Never return an unbounded list. Return a page with a clear way to get the next one. Cursor based paging is robust for large, changing datasets.

GET /v1/orders?limit=50&cursor=eyJpZCI6MTIzfQ

{
  "data": [ ... 50 orders ... ],
  "next_cursor": "eyJpZCI6MTczfQ",
  "has_more": true
}

Errors. Use one error shape across the whole API. A machine readable code lets clients branch on the problem. A human readable message helps the developer debug.

{
  "error": {
    "code": "invalid_email",
    "message": "The email field is not a valid address.",
    "field": "email"
  }
}

Auth, idempotency, and rate limiting

This is the layer that keeps your API safe and reliable under real traffic.

Auth. Send credentials in the Authorization header, usually a bearer token, and serve the API only over HTTPS. Do not put secrets in the URL or query string, because URLs end up in logs. Return 401 when the caller is not logged in and 403 when they lack permission.

Idempotency. Networks fail, so clients retry. Without care, a retried payment could charge a card twice. The fix is an idempotency key. The client sends a unique key with the request. If the server sees the same key again, it returns the first result instead of doing the work twice.

POST /v1/payments
Idempotency-Key: a1b2c3d4-unique-per-request
Authorization: Bearer your_token

# A retry with the same key returns the first result,
# so the customer is charged only once.

Rate limiting. Limits protect your API from abuse. When a client goes over, return 429 Too Many Requests, and include a Retry After value. In a multi-tenant product, set limits per tenant so one heavy customer cannot starve the rest. Our guide to multi-tenant SaaS architecture covers this in depth.

HTTP/1.1 429 Too Many Requests
RateLimit-Limit: 1000
RateLimit-Remaining: 0
Retry-After: 30

FAQ

What makes an API RESTful?

A RESTful API models the system as resources named with nouns, uses HTTP methods as the verbs, and returns proper status codes. It is stateless, meaning each request carries what it needs and the server keeps no client session between calls. The result is an API that is predictable and that standard tools and caches understand.

What is the difference between PUT and PATCH?

PUT replaces a whole resource. You send the full object, and the server makes it match what you sent. PATCH updates only the fields you include and leaves the rest alone. PUT is idempotent. Use PUT for a full replace and PATCH for a small, partial change.

Why does my API need idempotency keys?

Because clients retry after timeouts and dropped connections. Without protection, a retried create or payment can run twice and produce a duplicate record or a double charge. An idempotency key lets the server recognize a repeat and return the original result, which makes retries safe.

Working with Apex Logic

We design and build REST APIs that are clean, versioned, and safe to scale, with auth, pagination, and idempotency planned from the start. See our services or tell us what you are building for a fixed, fair quote.

References

MDN Web Docs, HTTP methods and status codes.
Stripe and GitHub public API docs, versioning, pagination, and idempotency patterns.
Apex Logic project data (2024 to 2026), production API builds.

Share: Story View

Related Tools

Content ROI Calculator Estimate value of content investments.

You May Also Like

How to Secure a Web Application
Web Development

How to Secure a Web Application

1 min read
Webhooks vs APIs: Which Should You Use
Web Development

Webhooks vs APIs: Which Should You Use

1 min read
Monolith vs Microservices for Startups
Web Development

Monolith vs Microservices for Startups

1 min read

Comments

Loading comments...