Skip to content
APIHiver

API Design Principles: 12 Rules for a Great API (2026)

API design principles explained in plain English: 12 practical rules for URLs, methods, errors, pagination, versioning, security and docs, with examples.

12 min readBy Mivaan Sanghani
In this post

Open an API for the first time and you can tell within five minutes whether somebody cared about the person using it. Clear names, a helpful error message, a request that just works: it feels like a good menu in a good restaurant. A confusing one, with half the options missing and no price list, makes you want to leave.

That difference has a name: API design. This guide gives you 12 plain-English rules for getting it right. They apply whether you are building an API for your own app, for customers, or to publish on a marketplace.

If you are brand new to the idea, an API is simply a way for one program to ask another program for something. An endpoint is one specific thing it can ask for, at its own web address. For more background, read what a REST API is first, then come back.

The 12 API design principles at a glance#

  1. Design for the person using it
  2. Name things with nouns, and keep addresses readable
  3. Use HTTP methods for what they mean
  4. Return the right status code
  5. Make errors helpful
  6. Be consistent everywhere
  7. Make lists safe: paginate, filter and sort
  8. Version from day one, and never break users
  9. Make requests safe to retry
  10. Be secure by default
  11. Tell people your limits
  12. Document with real examples

Now the detail for each one.

1. Design for the person using it#

The best API designers think like a customer, not like an engineer. Your database might have a table called usr_acct_tbl, but nobody wants to see that in a response.

Ask these questions before you write any code:

  • Who will use this? A beginner copying an example? A team that integrates it into a billing system?
  • What are they trying to get done? Design around the job, not around your internal structure.
  • What is the first thing they will try? Make that work in one request.

A useful test is the "first five minutes" test. Give your API to someone who has never seen it. If they cannot make a successful request within five minutes using only your docs, the design needs work.

Many teams also use a design-first approach: write down the endpoints and example responses (often in an OpenAPI file) and show them to users before building. Changing a document is cheap. Changing a live API is not.

2. Name things with nouns, and keep addresses readable#

In a REST API, the web address names a thing, and the HTTP method says what to do with it. So addresses should be nouns, not verbs.

AvoidBetter
/getAllOrdersGET /orders
/createOrderPOST /orders
/deleteOrder?id=42DELETE /orders/42
/user_get_by_id/42GET /users/42

A few simple naming rules:

  • Use plural nouns for collections: /orders, /users.
  • Nest to show ownership, but only one or two levels: /users/42/orders.
  • Pick one style and stick with it. Lower-case words separated by hyphens (/order-items) are common for addresses, and one consistent style inside your JSON.
  • Make addresses readable. /apis/weather/endpoints/current-weather tells a human, and a search engine, what the page is about. A long random ID does not.
  • Allow the odd action when needed. Some things do not fit a method, like cancelling an order. POST /orders/42/cancel is fine, as long as it is the exception and not the habit.

3. Use HTTP methods for what they mean#

Every web request starts with a method, and each one promises something. Following those promises means developers can guess how your API behaves without reading every page.

MethodMeaningSafe to repeat?
GETRead somethingYes
POSTCreate somethingNo
PUTReplace something completelyYes
PATCHChange part of somethingNot by default
DELETERemove somethingYes

The two mistakes we see most often are using GET to change data (a search engine or a link preview can then trigger it by accident) and using POST for everything. Our full guide to API request methods explains each one with examples.

The official definitions live in RFC 9110, the HTTP semantics standard. You do not need to read it, but it is the reference when you are unsure.

4. Return the right status code#

The status code is the first thing a program reads. It decides what happens next: show the data, ask the user to log in, try again later.

  • 2xx means success. 200 OK for a normal read, 201 Created when you made something, 204 No Content when it worked and there is nothing to return.
  • 4xx means the caller made a mistake. 400 for a bad request, 401 for "you are not logged in", 403 for "you are logged in but not allowed", 404 for "not found", 409 for a conflict, 422 for data that is well-formed but not valid, and 429 for too many requests.
  • 5xx means we made a mistake. 500 for an unexpected failure, 503 when you are temporarily unavailable.

The classic mistake is returning 200 OK with {"error": "something went wrong"} inside. It breaks every tool that trusts the status code, including monitoring, retries and caches. If it failed, say so with the status code.

5. Make errors helpful#

When something goes wrong, your error message is the only help the developer gets. A good error answers three questions: what happened, why, and what to do about it.

Compare these two:

{ "error": "Invalid request" }
{
  "type": "https://docs.example.com/errors/invalid-email",
  "title": "Your request parameters didn't validate.",
  "status": 422,
  "detail": "The 'email' field must be a valid email address, but 'john@gmial' was given.",
  "instance": "/signups/7f3a",
  "errors": [{ "field": "email", "message": "Not a valid email address" }]
}

The second one follows RFC 9457 "Problem Details for HTTP APIs" (published in 2023, replacing the older RFC 7807). It is a standard error format, sent with the content type application/problem+json, so you do not have to invent your own. Tools and developers already know how to read it.

Tips for good errors:

  • Use a stable type: a code or a docs link that never changes, so programs can react to it.
  • Write detail for a human. Say which field and what is wrong.
  • Never leak internals: no stack traces, no database names, no file paths.
  • Include a request ID so you can find the problem in your logs when a customer reports it.

6. Be consistent everywhere#

Consistency is what makes an API feel designed instead of grown. When one thing works a certain way, everything else should too. Developers learn your patterns once, then guess the rest correctly.

Check these:

  • Naming style in JSON: pick snake_case or camelCase and never mix them.
  • Dates and times: use ISO 8601 in UTC, like 2026-10-15T09:30:00Z, everywhere.
  • Money: send the amount and the currency together, and decide whether you use whole units or the smallest unit (cents, paise) and never switch.
  • IDs: always the same field name and type.
  • Empty values: decide how you show "nothing" (an empty list, null, or leaving the field out) and use it everywhere.
  • Response shape: if one list endpoint wraps results in {"data": [...]}, they all should.

A small habit helps a lot: keep a one-page style guide, and check every new endpoint against it before release.

7. Make lists safe: paginate, filter and sort#

If an endpoint returns a list, plan for that list growing. An endpoint that returns 50 items today might return 5 million next year, and a single huge response slows your server and crashes your users' apps.

Always paginate. There are two common ways:

  • Page and size (?page=3&limit=50): simple, and good for small data.
  • Cursor-based (?cursor=abc123&limit=50): better for big or fast-changing data, because it does not skip or repeat items when new records arrive.
{
  "data": [{ "id": "ord_1" }, { "id": "ord_2" }],
  "next_cursor": "eyJpZCI6Im9yZF8yIn0",
  "has_more": true
}

Set a sensible default and a maximum page size (for example, 50 by default and never more than 100), so no one can ask for everything at once.

Give users filters and sorting with plain parameters: ?status=paid&sort=-created_at (the minus meaning newest first). It stops people downloading everything just to find one item.

8. Version from day one, and never break users#

This is the most important rule on the list. People build their products on yours. If you rename a field, change a type or remove an endpoint, you can break their app overnight, and you may never hear why they left.

Breaking changes (never do these inside an existing version):

  • Removing or renaming a field or endpoint
  • Changing a field's type or meaning
  • Making an optional input required
  • Changing error codes people rely on

Safe changes (fine at any time):

  • Adding a new endpoint
  • Adding a new optional field to a response
  • Adding a new optional input

A few practical rules:

  • Put the version in the address, such as /v1/orders. It is easy to see, test and cache.
  • Release /v2 only for breaking changes, and keep /v1 running for a stated period.
  • Warn early. The Deprecation response header (RFC 9745, published in 2025) tells programs a resource is being retired, and a Sunset header (RFC 8594) can carry the date it stops working. Also tell people by email and in the docs.
  • Tell clients to ignore what they do not know, so adding fields never breaks them.

9. Make requests safe to retry#

Networks fail. A customer clicks "Pay", the connection drops, and their app does not know whether the payment went through. So it tries again. Without protection, you have charged them twice.

Some methods are idempotent by nature, which means repeating them gives the same result: GET, PUT and DELETE. POST is not. The fix is an idempotency key: the client sends a unique ID with the request, and your server remembers it.

await fetch("https://api.example.com/v1/payments", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(), // reuse the SAME key when retrying
  },
  body: JSON.stringify({ amount: 4999, currency: "INR" }),
});

If the server sees the same key twice, it returns the original result instead of doing the job again. Payment APIs have used this pattern for years. A standard Idempotency-Key header is being worked out at the IETF, but it is still a draft, so document exactly how your version behaves.

10. Be secure by default#

Security is not a feature you add at the end. Build these in from the start:

  • HTTPS only. Never accept plain HTTP.
  • Authenticate every request with an API key, a token or OAuth, depending on who is calling.
  • Check permission on every record. This is the big one. The OWASP API Security Top 10 (2023) lists broken object level authorization as the number one API risk. In plain words: a user logs in, then changes /orders/1042 to /orders/1043 and sees someone else's order. Your server must check, every time, that this user is allowed to see this exact record. Random IDs make guessing harder, but they are not a substitute for the check.
  • Give each key the minimum it needs (a read-only key for read-only jobs).
  • Validate all input: types, lengths and allowed values.
  • Return only what is needed. Do not send back a whole user record when the caller needs a name.
  • Never put secrets in the address. Web addresses end up in logs. Send keys in a header.

11. Tell people your limits#

Every API has limits, because without them one customer can slow everyone else down. The kind thing to do is to make those limits visible and predictable.

  • Return 429 Too Many Requests when someone goes over.
  • Add a Retry-After header saying how many seconds to wait.
  • Many APIs also send headers showing the limit, the number left and when it resets. These RateLimit headers are still being standardised, so describe yours clearly in the docs.
  • Write the limits down: requests per minute, daily or monthly quota, maximum body size and timeout.

On APIHiver, each plan shows its request quota on the pricing page, for exactly this reason: nobody should find out their limit by hitting it.

12. Document with real examples#

An API without good documentation is, in practice, an API without users. Developers skim. They look for one working example they can copy.

Great docs have:

  • A quick start that gets a first successful request in minutes
  • Every endpoint with its method, address, inputs, outputs and possible errors
  • Real example requests and responses, not placeholders like string
  • Code in the languages your users use (at least JavaScript and Python, plus a plain curl example)
  • A changelog, so people see what changed and when
  • A place to try it live without writing code

A machine-readable description such as an OpenAPI file is worth having too: it can generate docs, test tools and client libraries from one source of truth.

A quick design review in 30 minutes#

Before you release a new endpoint, run it past this list:

  • The address is a clear noun and reads well
  • The right HTTP method is used
  • Success and failure return the right status codes
  • Errors say what happened and how to fix it
  • Names, dates and money match the rest of the API
  • Lists are paginated with a maximum size
  • It sits under a version, and nothing existing was broken
  • Creating things is safe to retry
  • It requires authentication and checks permission on each record
  • Limits are enforced and documented
  • There is at least one real example in the docs

Common mistakes to avoid#

  • Leaking your database into the API. Customers should not see your internal table names or structure.
  • Returning 200 for errors. It breaks monitoring, retries and caching.
  • Changing things without a version. The fastest way to lose users.
  • Unbounded lists. They work in testing and fail at scale.
  • Vague errors. "Something went wrong" costs hours of support time.
  • Forgetting the second check. A valid login is not permission to see every record.
  • Documenting last. If docs are an afterthought, users feel it.

Summary#

  • Design for the user. Think about the first five minutes, not your database.
  • Nouns for addresses, the right method for the action, the right status code for the result.
  • Errors should explain. Use the RFC 9457 Problem Details format.
  • Stay consistent, paginate every list, and version from the start.
  • Never break existing users. Add freely, change only through a new version with warning.
  • Make retries safe with idempotency keys, secure every record (not just the login), and publish your limits.
  • Document with real examples, and run every new endpoint through the review checklist.

Next, put these rules to work with our guides to API request methods, REST API vs SOAP API and what a REST API is. If you run an API in production, our guide to production habits for image APIs shows these ideas (retries, limits, fallbacks) in practice. Building for AI agents? See MCP vs CLI vs Skills: Live Web Data for AI Agents, and for clean, predictable data see 6 International Standard Formats Every API Should Use. To see how to judge an API's limits and pricing before you depend on it, read our GS1-128 barcode reader API comparison.

Try APIs on the APIHiver marketplace

Discover free and paid APIs for travel, finance, AI, weather, maps and more. Test each endpoint in your browser and use one key for all of them.

Share this post

Frequently asked questions

What are the principles of API design?
Good API design follows a few core principles: design for the person using it, name things clearly with nouns, use HTTP methods and status codes for what they mean, return helpful errors, stay consistent, paginate lists, version from day one, make requests safe to retry, secure every request, explain your limits, and document with real examples. The 12 rules in this guide cover each of these.
What is the most important rule of API design?
Never break the people already using your API. Developers build their own products on top of yours, so renaming a field or changing a response without warning can break their app. Add new things freely, but change or remove existing things only through a new version and a clear warning period.
What is the difference between REST API design and general API design?
REST is one style of API that uses web addresses and standard HTTP methods. General API design principles, such as consistency, clear errors, security, versioning and good documentation, apply to every kind of API, including REST, GraphQL and gRPC. REST adds its own rules on top, such as using nouns for addresses and the right HTTP method for each action.
Should API URLs use nouns or verbs?
Nouns. The address names the thing, such as /orders or /users/42, and the HTTP method says what to do with it: GET reads, POST creates, PUT or PATCH changes and DELETE removes. Put verbs in the address only for rare actions that do not fit a method, such as /orders/42/cancel.
How should I version an API?
The simplest way is to put the version in the address, such as /v1/orders. It is easy to see, test and cache. Release a new version only for breaking changes, keep the old one running for a stated period, and warn users early, for example with a Deprecation response header (RFC 9745) and a date in your docs.
What should an API error response contain?
The right HTTP status code, a stable error type, a short human-readable title, a detail message that says what to fix, and ideally a link to the docs. RFC 9457, the current standard for error responses, defines a ready-made JSON format called Problem Details that includes these fields.
How do I make an API secure by design?
Use HTTPS everywhere, authenticate every request, and check on every request that this user is allowed to touch this exact record. That second check, called object-level authorization, is the number one risk on the OWASP API Security Top 10. Also limit request rates, validate all input and never return more data than the caller needs.