Skip to content

Engineering · 3 min read · Updated

API design practices that save you pain later

An API is a promise to every app and partner that uses it. Design decisions made in week one are expensive to undo in year two. Here's what to get right early.

By Xyvin Technologies

Once an API is in use by your mobile app, your website and perhaps a few partners, every change becomes a negotiation. That's why the decisions you make before the first release matter so much. The following practices keep APIs easy to use, safe to change and cheap to support.

Design the API before writing the code

Write the API description first, typically as an OpenAPI document, and review it with the people who will use it: frontend developers, mobile developers, integration partners. Changing a document takes minutes. Changing a live API takes months.

Name things the way your business does

Resources should match real concepts and use plural nouns: /orders, /members, /invoices. Use HTTP methods for actions (GET to read, POST to create, PATCH to update, DELETE to remove) rather than verbs in URLs. Consistency matters more than any single convention, so pick one style and stick to it.

Return errors people can act on

A bare "400 Bad Request" helps nobody. Use the right status code and a consistent error body that says what went wrong and which field caused it:

  • 400 for invalid input, with field-level messages
  • 401 / 403 for missing or insufficient permissions
  • 404 when something doesn't exist
  • 409 for conflicts, such as a duplicate booking
  • 429 when a client is sending too many requests

Version from the start

Put a version in the path or a header from the first release. When you need a breaking change, release a new version, give clients a clear deprecation date, and keep the old version running until then. Non-breaking additions, such as a new optional field, don't need a new version.

Paginate every list

Any endpoint that returns a list will eventually return a very long one. Paginate from day one, and for large or fast-changing data use cursor-based pagination, which stays reliable when records are added while someone is paging through.

Make retries safe

Networks fail, and clients retry. If a payment or order request is retried, it must not create a duplicate. Support an idempotency key on create operations so the same request can safely be sent twice.

Secure it properly

  • HTTPS everywhere, with no exceptions.
  • Short-lived access tokens, and scopes that limit what each client can do.
  • Validate every input on the server, even if the app already did.
  • Rate-limit by client to protect against abuse and runaway scripts.
  • Never return more data than the client needs, especially personal data.

Use webhooks instead of constant polling

If partners need to know when something changes, such as a payment succeeding or an order shipping, send them a signed webhook rather than making them ask every minute. It's faster for them and cheaper for you.

Document and monitor

Good documentation includes working examples, not just field lists. Once live, track response times, error rates and which endpoints and versions are used, so you know who will be affected by a change before you make it.

REST or GraphQL?

Both work well. REST is simpler to cache, secure and explain to partners. GraphQL helps when many different screens need different slices of complex, related data. For most business systems, a well-designed REST API is the pragmatic default.

Need an API for your product, or need your existing systems connected? See how we approach integrations.

Share:LinkedInXWhatsApp

Need help with a project like this?

Share a few details and we'll reply within 24 hours with questions, ideas and next steps. Wherever you are, we'll find a time that works.