If Your API Needs a Long Explanation It Is Probably Too Complex

by Eric Hanson, Backend Developer at Clean Systems Consulting

The explanation as a diagnostic

Before you write a paragraph of documentation for an endpoint, stop and read what you are about to write. If you are explaining why a field has different semantics depending on request context, the field is probably two different fields. If you are explaining the correct sequence of calls required to accomplish a single task, that task is probably one endpoint. If you are documenting exceptions to the general behavior, the general behavior probably needs rethinking.

Documentation should clarify, not compensate. An API endpoint that requires a tutorial is an API endpoint that has leaked its implementation into its interface.

Symptoms of accidental complexity

Context-dependent field semantics: A request field that means different things based on other fields in the same request:

{
  "type": "subscription",
  "amount": 100,
  "interval": "monthly"  // only valid if type is subscription; ignored otherwise
}

The consumer must know the rule. When they forget and set interval on a one-time charge, it is silently ignored. The fix is two separate endpoints or two separate request schemas — POST /charges and POST /subscriptions.

Side effects encoded in a single endpoint: A POST /orders that creates the order, charges the payment method, sends a confirmation email, updates inventory, and notifies a warehouse system — all in one synchronous call. When any one of these steps fails, the client receives an error without knowing which step failed or what state things are in.

Complex side effects belong in an event-driven model where the initial response confirms acceptance, and each downstream step is a separate observable event.

Implicit state machine: An endpoint whose behavior depends on the current state of the resource being operated on, without explicitly modeling the state machine:

"You can call PATCH /subscriptions/{id} with status: 'paused' only if the subscription is currently active. If it is already paused, you get a 409. If it is cancelled, you get a 422. If it is in trial, you get a 400 unless you also provide resume_date."

The consumer must memorize this. The fix is to make the state machine explicit — model the allowed transitions, return clear errors that name the current state and the transition attempted, and document the state machine as a diagram rather than prose.

The right level of abstraction

One indicator of appropriate API design: the vocabulary in your API matches the vocabulary in your domain, not your database schema.

If your users think in terms of "subscriptions" and "plans" and "billing cycles," but your API exposes "recurring_payment_schedules" and "product_tier_assignments," the consumer has to translate between two vocabularies constantly. That translation lives in the consuming code and in every developer's head.

Name things the way your users think about them. POST /subscriptions is better than POST /recurring-payment-schedule-configurations even if the latter is more precisely accurate to the underlying data model.

The endpoint count as a design signal

More endpoints is not better. An API with 200 endpoints for a domain that should have 30 has usually modeled its internal service decomposition rather than its external use cases.

Audit which endpoints actually get called. In practice, most APIs have a long tail of endpoints that account for very little traffic. These are candidates for consolidation or deprecation.

A useful question for every endpoint: what single task does this enable? If the answer is "it depends" or requires a conjunction ("it does X and also Y"), the endpoint is probably doing too much.

When simplification requires breaking changes

Sometimes you cannot simplify without a version bump. A response field that currently serves two purposes cannot be split into two fields without clients updating their parsing logic.

In these cases:

  1. Design the simpler version in v2 from the start, before building v2 features.
  2. The migration from v1 is the opportunity to pay down the complexity debt.
  3. Document the complexity in v1 clearly and document the simplification in the v2 migration guide — "if you were working around X in v1, you no longer need to."

Complexity deferred to documentation is still complexity. The document is evidence that the design needs attention — use it as input to the next design iteration, not as a permanent substitute for a simpler interface.

Scale Your Backend - Need an Experienced Backend Developer?

We provide backend engineers who join your team as contractors to help build, improve, and scale your backend systems.

We focus on clean backend design, clear documentation, and systems that remain reliable as products grow. Our goal is to strengthen your team and deliver backend systems that are easy to operate and maintain.

We work from our own development environments and support teams across US, EU, and APAC timezones. Our workflow emphasizes documentation and asynchronous collaboration to keep development efficient and focused.

  • Production Backend Experience. Experience building and maintaining backend systems, APIs, and databases used in production.
  • Scalable Architecture. Design backend systems that stay reliable as your product and traffic grow.
  • Contractor Friendly. Flexible engagement for short projects, long-term support, or extra help during releases.
  • Focus on Backend Reliability. Improve API performance, database stability, and overall backend reliability.
  • Documentation-Driven Development. Development guided by clear documentation so teams stay aligned and work efficiently.
  • Domain-Driven Design. Design backend systems around real business processes and product needs.

Tell us about your project

Our offices

  • Copenhagen
    1 Carlsberg Gate
    1260, København, Denmark
  • Magelang
    12 Jalan Bligo
    56485, Magelang, Indonesia

More articles

The Machine Behind My Backend Systems

This is the setup we use to deliver backend work that’s fast, reliable, and efficient. Optimized tools help us build systems anywhere, anytime, without compromise.

Read more

How Seoul Tech Startups Are Filling Senior Backend Gaps Without Competing With the Big Players

Competing with Samsung and Kakao for backend engineers is a losing game for most startups. The ones shipping consistently have stopped playing it.

Read more

Async Is Not a Compromise — It Is How the Best Remote Backend Teams Actually Work

Async remote work has a reputation as the fallback option when synchronous isn't possible. That reputation is wrong, and the teams doing backend development best know it.

Read more

Securing Your API Is More Than Just Adding a Token

Authentication is the front door. An API with only a front door is still full of open windows. Here is what a complete API security posture actually covers.

Read more