Skip to main content

How to desgin REST APIs that actually works

· 3 min read
Rohit Jain
Head of Engineering @ American Chase

When your team sets out to build an API, it’s tempting to jump straight into writing code. But most APIs fail not because they lack fancy technology, but because they are confusing, inconsistent, or hard to maintain.

In this post, I’ll walk you through a practical approach to designing a REST API that actually works—clear to understand, easy to evolve, and a delight for developers to consume.

Let’s imagine we’re building an online bookstore API. I’ll use this example to illustrate key principles step by step.


Start With Clear Goals

Before you even name your endpoints, step back and clarify:

  • What resources do you need?

    • Books
    • Authors
    • Orders
    • Users
  • Who will consume this API?

    • Mobile apps
    • Web dashboards
    • Third-party partners
  • What are the core workflows?

    • Browsing books
    • Placing orders
    • Managing inventory

Taking the time to define this will save you costly redesigns later.


Use Consistent Naming

A predictable naming scheme makes your API easier to adopt:

Use nouns, not verbs
Keep names plural
Keep paths tidy

Good examples:

GET /books
POST /orders
GET /users/{id}

Problematic examples:

POST /createBook
GET /getOrders

This small detail pays dividends in clarity.


Use HTTP Methods Properly

Every operation should match an established HTTP verb:

  • GET – Retrieve data
  • POST – Create new records
  • PATCH – Update records partially
  • DELETE – Remove records

For example:

POST /books
creates a book, while:
retrieves details of one.

Authentication Matters

Always secure your API:

  • Require an API Key in headers:
  • Enforce HTTPS to protect sensitive data.

The Bookstore API Example

Here’s a practical sketch of what your endpoints might look like:


List Books

Query Parameters:

  • author_id
  • search
  • sort (e.g., -published_at)
  • page
  • limit

Response:

{
"data": [
{
"id": "b1",
"title": "Clean Code",
"author_id": "a1",
"published_at": "2008-08-01"
}
],
"meta": {
"total": 120,
"page": 1,
"limit": 20
}
}

Create Books

POST /books

Request

{
"title": "Domain-Driven Design",
"author_id": "a2",
"published_at": "2003-08-30",
"price": 45.0
}

Response

201 Created
{
"data": {
"id": "b2",
"title": "Domain-Driven Design"
}
}

Retrieve an Order

GET /orders/{id}
{
"data": {
"id": "o1",
"status": "processing",
"items": [
{ "book_id": "b1", "quantity": 1 },
{ "book_id": "b2", "quantity": 2 }
],
"total": 115.0
}
}

Standard Error Responses

To build trust with developers, always return consistent error messages:

Example: Not Found

{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Book not found"
}
}

Example: Validation Error

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Missing required field: title"
}
}

Use Clear HTTP Status Codes

CodeMeaning
200OK
201Created
204No Content
400Bad Request
401Unauthorized
403Forbidden
404Not Found
409Conflict
422Validation Error
500Server Error

Version Your API

Always prefix your paths with a version number:

/v1/books

This gives you room to grow and change without breaking existing clients.

A Checklist for Reliable APIs

Here’s a quick reference you can share with your team:

✅ Clear, consistent resource names ✅ Predictable HTTP verbs ✅ Standard JSON response formats ✅ Pagination, filtering, and sorting ✅ Consistent error messages ✅ Authentication enforced ✅ Versioning in place ✅ Solid documentation

Final Thoughts

Great APIs are not about buzzwords—they’re about clarity, consistency, and trust. When you take the time to design with purpose, you empower your teams and your customers to build with confidence.