Should you use verbs in URL?
In REST, the HTTP method is responsible for the action, not the path string.
Junior Level
For pure REST, verbs in URLs are not recommended — the action is expressed by the HTTP method. However, in practice many APIs (Stripe, GitHub) use verbs for complex operations that don’t fit into CRUD.
In REST, the HTTP method is responsible for the action, not the path string.
Why are verbs bad?
- ❌
GET /deleteUser/1— verb in URL, GET method for deletion (very bad!) - ❌
POST /saveOrder— verb, this is RPC, not REST - ✅
DELETE /users/1— correct: DELETE method, users resource - ✅
POST /orders— correct: POST method, orders resource
Correct approach:
// Incorrect:
POST /deleteUser/1
POST /saveOrder
GET /findUsers?name=Ivan
// Correct:
DELETE /users/1
POST /orders
GET /users?name=Ivan
Simple rule:
- URI is a noun (resource)
- HTTP Method is the verb (action)
Middle Level
Why are verbs in URLs a problem?
- Caching semantics violation: Proxies know that
GETis safe. If there’s aGET /delete-all, the proxy might “pre-fetch” that URL - Documentation complexity: Instead of a standard set of actions — an endless list of custom methods
- RPC instead of REST:
/deleteUser,/saveOrderturns REST into Remote Procedure Call
“Resource as action” pattern
If business logic requires a complex process, a Senior architect turns the action into a resource.
Example: Cancel an order
- Acceptable, but there are better options:
POST /orders/1/cancel— GitHub, Stripe use this approach. - Good (PATCH):
PATCH /orders/1with body{"status": "CANCELLED"} - Better (Resource-based):
POST /orders/1/cancellation— we create a “cancellation entity”. This allows storing metadata: who cancelled, when, for what reason
Example: Search
- Bad:
GET /findUsers?name=Ivan - Good:
GET /users?name=Ivan
“State Machine” design in REST
If the application is a complex state machine (application lifecycle), don’t create endpoints /approve, /reject, /review. Use HATEOAS: the server returns the current state and a list of allowable links for transitions.
Performance
- Using verbs often hides inefficient “heavy” operations
- The resource approach forces thinking about how data is stored and indexed
- Verb-based endpoints in
POSTare often forgotten to be made idempotent.- Idempotency — a property: repeated call produces the same result.
- POST is not idempotent by default (two POSTs = two resources).
- If
POST /orders/1/cancelis called twice — the order gets cancelled twice with side effects.
Senior Level
Turning actions into resources
Example: Calculator
For mathematical calculations or data migrations where there’s no explicit resource, it’s acceptable to use a noun-controller:
POST /calculators/tax-estimator
This is still not a verb, but a departure from pure CRUD.
HATEOAS and State Machine
HATEOAS implements the State Machine pattern at the network protocol level:
- The server returns the current state of the resource
- Along with it — a list of allowable links for transitions
- The client follows the link without knowing whether it’s a “verb” or not
- This radically reduces coupling between frontend and backend
Diagnostics
- Log Analysis: It’s harder to build analytics funnels for endpoints with verbs. The resource approach allows grouping requests by entities
- Security: Verbs in URLs become a target for vulnerability scanners, as they reveal application logic (Command Injection risks)
Edge Cases
- Legacy systems: When integrating with old SOAP/XML systems, you often have to use method “tunneling”, but even there try to wrap them in resource wrappers at the API Gateway level
- Controller endpoints: It’s acceptable to use a noun-controller for complex operations without an explicit resource
Interview Cheat Sheet
Must know:
- For pure REST, verbs in URLs are not recommended — the action is expressed by the HTTP method
- URI = noun (resource), HTTP Method = verb (action)
- GET /deleteUser — critical error: proxy may pre-fetch and accidentally delete
- “Resource as action” pattern: POST /orders/1/cancellation instead of POST /orders/1/cancel
- HATEOAS implements State Machine: server returns current state + allowable transitions
- Verbs in URLs expose application logic and become targets for vulnerability scanners
- For mathematical calculations, a noun-controller is acceptable: POST /calculators/tax-estimator
Common follow-up questions:
- How to properly cancel an order? — PATCH /orders/1 with
{"status": "CANCELLED"}or POST /orders/1/cancellation - Why is GET /deleteAll bad? — Browsers and proxies may pre-fetch GET, which would trigger deletion
- When are verbs acceptable? — Legacy integrations, RPC endpoints, but better to wrap in resource wrappers
- How does HATEOAS replace verbs? — Server returns links to allowable actions for the current state
Red flags (DO NOT say):
- “Verbs in URLs are fine for REST API” — they violate REST semantics and caching
- “POST /saveUser is REST” — that’s RPC, not REST
- “GET /logout is a good approach” — GET must be safe, browsers may pre-fetch
- “Verbs simplify documentation” — on the contrary, they break the standard set of actions and complicate OpenAPI
Related topics:
- [[How to properly name REST endpoints]]
- [[What is RESTful API design]]
- [[What is HATEOAS]]
- [[What are the main HTTP methods used in REST]]
- [[Is POST idempotent]]