Most bad APIs aren't one catastrophic decision — they're ten small, individually reasonable-seeming choices that compound. This is the checklist Taliferro actually uses when reviewing an API before it ships.
Published: 17 Apr 2023 · Updated: 10 Aug 2026
Co-Founder Taliferro
Most bad APIs aren't bad because of one catastrophic decision — they're bad because of ten small, individually reasonable-seeming choices that compound. Here are the ten that show up most often, what they cost you in practice, and how to avoid each one.
Current guidance: This reflects current REST and HTTP best practices, stronger security baselines (OAuth 2.1/PKCE, mTLS in sensitive environments), and clearer guidance on pagination, error payloads, and versioning strategies.
An endpoint name should tell a developer what it does without needing the docs open. Endpoints like /proc2 or /handleData force every integrator to guess, test, and re-guess. Name resources as nouns (/customers/{id}/orders), not verbs or internal jargon only your team understands.
Mixing camelCase, snake_case, and PascalCase across the same API means every client has to special-case each endpoint's quirks. Pick one convention, document it, and enforce it in code review — consistency here is what makes an API guessable instead of memorized.
Deep nesting like /companies/{id}/departments/{id}/teams/{id}/members/{id}/tasks looks organized and is actually a maintenance trap — every level adds a parameter clients must track correctly. Two levels of nesting is usually the practical ceiling; beyond that, flatten with query parameters or separate top-level resources.
Versioning matters for compatibility, but bumping the version for every minor field addition forces clients into a constant, unnecessary upgrade treadmill. Reserve a new version for breaking changes; additive, backward-compatible changes don't need one.
An API without real docs — actual request/response examples, not just a field list — pushes every integration question into your support queue. Generate docs from your schema (OpenAPI/Swagger) so they can't silently drift out of sync with the actual behavior.
Using GET to delete something, or POST for an operation that's supposed to be safely repeatable, breaks the assumptions every HTTP client, cache, and proxy makes about your API. Match methods to their semantics: GET reads, POST creates, PUT/PATCH updates, DELETE removes — no exceptions for convenience.
"Something went wrong" tells a developer nothing actionable. A good error response names exactly what field failed, why, and what a valid value looks like — the difference between a five-minute fix and a support ticket.
// ❌ Bad: ambiguous error
HTTP/1.1 400 Bad Request
Content-Type: application/json
{ "error": "Something went wrong" }
// ✅ Good: actionable, consistent shape
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"code": "INVALID_PARAMETER",
"message": "Query parameter 'limit' must be an integer between 1 and 100.",
"details": [
{ "field": "limit", "reason": "out_of_range", "min": 1, "max": 100 }
],
"traceId": "a1b2c3d4"
}
}
An endpoint that returns every record in one response works fine in testing with 50 rows and falls over in production with 500,000. Build pagination in from day one — retrofitting it later is a breaking change for every existing client.
// ✅ Recommended cursor-based pagination
GET /v1/customers?limit=50&cursor=eyJpZCI6IjEyMzQ1In0
HTTP/1.1 200 OK
Content-Type: application/json
{
"items": [ /* ... */ ],
"page": {
"limit": 50,
"next": "eyJpZCI6IjU2Nzg5In0",
"prev": null
}
}
// Include RFC 5988-style link headers for clients
Link: <https://api.example.com/v1/customers?limit=50&cursor=eyJpZCI6IjU2Nzg5In0>; rel="next"
Returning 200 on a failed request, or 404 for something that actually succeeded, breaks every client and monitoring tool that relies on status codes to know what happened without parsing the body. Use codes as intended: 2xx for success, 4xx for client errors, 5xx for server errors — and be consistent about which specific code maps to which failure.
Security bolted on after launch is security done wrong — missing rate limits, weak or absent authentication, and sensitive data returned in responses nobody audited. Build authentication, authorization, and rate limiting in from the start; retrofitting them onto an API already in production use is far more disruptive than designing for them up front.
Want a quick, objective read on your API? Take our short assessment and get an instant score across naming, versioning, pagination, error design, and security baselines.
None of these ten mistakes are exotic — they're the default outcome of shipping fast without a naming convention, a pagination plan, or a security review. Catching them early, before clients depend on the broken behavior, is far cheaper than fixing them after launch.
Tyrone ShowersTypical mistakes include unclear endpoint naming, inconsistent conventions, over-nesting resources, poor versioning, ignoring pagination, misusing HTTP methods and status codes, unhelpful error messages, and weak security.
Adopt consistent naming, document thoroughly, return predictable status codes, implement pagination and filtering, use semantic HTTP methods, and secure authentication and authorization from the start.
Choose a clear, consistent approach (e.g., URI versioning or header-based) and deprecate responsibly with documentation and migration timelines.
Turn the article into action with API consulting, connect it to the momentum system, or show us the integration problem.
Want this fixed on your site?
Tell us your URL and what feels slow. We’ll point to the first thing to fix.
Explore Taliferro's free tools: Ask TODD · Find · Email Signature Builder · SayIt · Lead Vault · Meet Maya — or become an affiliate.
More from the blog