Backend·October 8, 2025·3 min read

REST API Design Best Practices

Practical conventions for resource naming, versioning, error handling, and pagination that make an API pleasant to integrate against — and keep it stable as it grows.

Beginner
REST APINode.jsTypeScript
NT

NavikaTech

Updated January 5, 2026

Reading Progress
0%

Most REST API design debates are really consistency debates. Any reasonable convention beats an inconsistent mix of conventions, because the cost of a REST API isn't in any single endpoint — it's in the cognitive overhead an integrator pays every time the pattern changes from one endpoint to the next.

Resources are nouns, methods are verbs

ActionBadGood
List ordersGET /getOrdersGET /orders
Create orderPOST /createOrderPOST /orders
Get one orderGET /order?id=123GET /orders/123
Cancel an orderPOST /orders/123/doCancelPOST /orders/123/cancel or PATCH /orders/123

Version from day one

It's tempting to skip versioning for a v1 API — 'we'll add it when we need v2.' The problem is that by the time you need v2, every existing client is already depending on unversioned URLs, and introducing versioning becomes a breaking change in itself. Bake /v1/ into the URL structure even if no v2 ever ships.

routes.tstypescript
// Version in the URL path — visible, cacheable, and easy for
// integrators to pin to in their own client code.
app.use("/v1/orders", ordersRouterV1);
app.use("/v1/users", usersRouterV1);

// Alternative: header-based versioning (Accept: application/vnd.api+json;version=1)
// is more "correct" per REST purists but meaningfully harder for most
// integrators to discover and use correctly. Path versioning wins on
// pragmatism for the majority of public APIs.

A consistent error envelope

Nothing frustrates API integrators faster than every endpoint returning errors in a slightly different shape. Standardize on one envelope, loosely modeled on RFC 7807, and use it everywhere without exception.

error-response.jsonjson
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The 'email' field must be a valid email address.",
    "field": "email",
    "requestId": "req_8f2a1c9d"
  }
}

Pagination: cursor-based over offset

Offset pagination (?page=2&limit=20) is simple but breaks under concurrent writes — insert a row while a client is paginating and they'll see duplicates or skip records entirely. Cursor-based pagination is more robust for any dataset that changes while being read.

pagination.tstypescript
interface PaginatedResponse<T> {
  data: T[];
  nextCursor: string | null;
}

app.get("/v1/orders", async (req, res) => {
  const limit = Math.min(Number(req.query.limit) || 20, 100);
  const cursor = req.query.cursor as string | undefined;

  const orders = await db.order.findMany({
    take: limit + 1, // fetch one extra to know if there's a next page
    ...(cursor && { cursor: { id: cursor }, skip: 1 }),
    orderBy: { id: "asc" },
  });

  const hasMore = orders.length > limit;
  const data = hasMore ? orders.slice(0, -1) : orders;

  const response: PaginatedResponse<Order> = {
    data,
    nextCursor: hasMore ? data[data.length - 1].id : null,
  };
  res.json(response);
});
A REST API's quality is measured by how few support tickets it generates, not by how closely it follows the spec. — Arjun Mehta, Principal Software Engineer, NavikaTech

Conclusion

Consistent naming, day-one versioning, a single error envelope, and cursor-based pagination cover the majority of what makes a REST API pleasant to integrate against. None of these are exotic — the discipline is applying them uniformly across every endpoint, forever, even under deadline pressure.

Key Takeaways

  • Model resources as nouns and use HTTP methods as verbs consistently — this alone eliminates most API design debates.
  • Version from day one, even if v1 is the only version that ever ships — retrofitting versioning later breaks every existing client.
  • A consistent error envelope across every endpoint saves integrators significant debugging time.
  • Cursor-based pagination scales better than offset pagination for any dataset that changes while being paginated.

Recommended Resources

Share this article
NT
NavikaTech·Engineering Team

NavikaTech

NavikaTech shares practical engineering notes on web development, app development, custom software, automation, AI, and long-term software maintenance.

Related Articles

Stay Updated With Modern Software Engineering

One email, occasionally — practical engineering writing from the NavikaTech team, no noise.