5 Common REST API URI Design Mistakes That Break Your API Architecture
Why does your REST API feel fragile, hard to evolve, and tightly coupled to your database? The problem often starts with URI design. I’ve seen the same five mistakes repeat across projects—verbs in URIs, database mirroring, chatty APIs, deep nesting, and singular collections. Each one breaks the REST model in a different way.
Mistake 1: Using Verbs Instead of Nouns
This is the most common mistake. Developers treat URIs like function names.
POST https://api.contoso.com/create-orderPOST https://api.contoso.com/delete-customer/5GET https://api.contoso.com/get-productsWhy is this wrong? HTTP methods already define actions. POST creates, DELETE removes, GET retrieves. When you put verbs in URIs, you’re duplicating information and breaking REST conventions. A URI should identify a resource, not describe an operation.
POST https://api.contoso.com/ordersContent-Type: application/json
{"productId": 2, "quantity": 4, "customerId": 1}
DELETE https://api.contoso.com/customers/5
GET https://api.contoso.com/productsThe URI identifies the resource. The HTTP method defines what you do with it. This separation makes your API predictable and consistent.
Mistake 2: Mirroring Database Table Structure
Your database has tables. Your API has resources. These are not the same thing.
GET https://api.contoso.com/database/orders_tableGET https://api.contoso.com/tables/users/join/roles_viewWhen you expose database tables directly, you create several problems. First, you increase your attack surface—hackers can probe your schema through your API. Second, you leak implementation details that should stay internal. Third, any database refactoring breaks your API contract.
GET https://api.contoso.com/orders/99GET https://api.contoso.com/users/5/rolesModel business entities, not storage structures. Your API should represent what the application does, not how it stores data. Add a mapping layer between your database and API to isolate changes. When you rename a table or split it across shards, your API stays stable.
Mistake 3: Creating Chatty APIs
Some developers go too far in the opposite direction—creating a separate endpoint for every attribute.
GET https://api.contoso.com/orders/1/valueGET https://api.contoso.com/orders/1/productsGET https://api.contoso.com/orders/1/statusGET https://api.contoso.com/orders/1/customerThis forces clients to make multiple requests for related data. Each round-trip adds latency. Under load, this pattern kills performance. Your servers handle more requests than necessary, and your clients waste bandwidth.
GET https://api.contoso.com/orders/1
Response:{ "id": 1, "value": 199.99, "status": "shipped", "products": [...], "customer": {...}}Denormalize related data into larger resources. But don’t go to extremes either—fetching a 500KB payload when you need an ID is equally problematic. Find the balance based on how clients actually use your data.
Mistake 4: Nesting Relationships Too Deep
Deep hierarchies seem logical until you try to maintain them.
GET https://api.contoso.com/customers/1/orders/99/products/5/variants/12DELETE https://api.contoso.com/customers/1/orders/99/products/5/variants/12/images/7URIs like this are hard to parse, cache, and evolve. When your business model changes—and it will—you’ll break every client using these endpoints. The Azure Architecture Center recommends keeping URIs simpler than collection/item/collection.
GET https://api.contoso.com/customers/1/orders
GET https://api.contoso.com/orders/99/products
GET https://api.contoso.com/products/5/variants/12Flatten your hierarchy. Use HATEOAS links in responses to guide clients to related resources. This keeps your URIs short and gives you flexibility to restructure relationships without breaking clients.
Mistake 5: Mixing Up Singular and Collection URIs
Consistency matters. When you mix singular and plural nouns, routing becomes confusing.
GET https://api.contoso.com/customer # Collection endpoint?GET https://api.contoso.com/customers/5 # Item endpointGET https://api.contoso.com/order/5 # Inconsistent namingGET https://api.contoso.com/products # Now plural?This confuses developers and breaks conventions. Frameworks expect collection/{id} patterns for routing.
GET https://api.contoso.com/customers # CollectionGET https://api.contoso.com/customers/5 # Item from collectionGET https://api.contoso.com/orders # CollectionGET https://api.contoso.com/orders/5 # Item from collectionGET https://api.contoso.com/products # CollectionGET https://api.contoso.com/products/5 # Item from collectionUse plural nouns for collections. This convention makes your API predictable: /resource-name for the collection, /resource-name/{id} for a specific item. Everyone knows what to expect.
Summary
In this post, I covered five URI design mistakes that break REST APIs. Verbs in URIs ignore what HTTP methods already express. Database mirroring couples your API to implementation details. Chatty APIs kill performance with unnecessary round-trips. Deep nesting creates unmaintainable hierarchies. Inconsistent singular/plural naming breaks developer expectations. Fix these by designing around business entities with plural nouns, keeping hierarchies simple, and using HTTP methods for actions. Your API becomes easier to evolve, more secure, and more performant.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments