Question 13 · Section 6

Should you use verbs in URL?

In REST, the HTTP method is responsible for the action, not the path string.

Language versions: English Russian Ukrainian

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?

  1. Caching semantics violation: Proxies know that GET is safe. If there’s a GET /delete-all, the proxy might “pre-fetch” that URL
  2. Documentation complexity: Instead of a standard set of actions — an endless list of custom methods
  3. RPC instead of REST: /deleteUser, /saveOrder turns 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/1 with 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
  • 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 POST are 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/cancel is 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]]