← Back to the section

CRUD operations (create, read, update, delete) are not always enough. Sometimes you need to reference a resource without a concrete ID — "my profile", "the latest deployment". Sometimes you need to express a business command — "confirm an order", "cancel a subscription". REST has well-established techniques for both cases.

The diagram below shows both techniques at once: when me really selects something, and what changes in logs and permissions once a domain command is named directly in the path.

what the client sends four domain commands what the server does consequence GET /users/me ← a regular user, sub=42 in the token GET /users/42 ← an admin views someone else's profile me → 42 from the token both requests reach the same getUser(id) handler — only the segment differs an admin could pass someone else's ID — so the me segment is justified the client does not need to store its own userId me is justified: one path serves both the user and the admin GET /users/me/orders ← the same sub=42 in the token GET /orders ← exactly the same response me → 42, and no other value is possible the owner comes from the token anyway; nobody gets someone else's orders nothing to choose — me is redundant, GET /orders is enough no scenario with someone else's ID — no alias either me is redundant: the segment selects nothing, the response is the same confirm cancel ship refund PATCH /orders/42 · {"status": "CANCELLED"} all four commands share one path; the command name stays in the field the log shows the same line four times: PATCH /orders/42 · order updated one permission for all four operations: orders:write PATCH hides the command: one log line and one permission for four operations POST /orders/42/confirm · /cancel · /ship · /refund four paths, four handlers; the command name is in the URL four different lines in the log — you can see what actually happened four permissions: orders:confirm, orders:cancel, orders:ship, orders:refund an action names the command: four log lines and four separate permissions

A path segment carries meaning: the server expands me into the ID from the token — but only where an administrator could pass someone else's ID. Four domain commands sent through PATCH give one log line and one permission for everything; as actions they give four paths, four log lines and four separate permissions.

Alias segments: a shortcut instead of an ID

A typical REST path looks like this: GET /users/42. The client knows the user's ID and substitutes it. But what if the client does not know the ID — it wants "the current user", "the latest deployment", "the primary payment card"?

An alias segment is a reserved word in the path instead of an ID. The server itself figures out from context which specific object is meant.

me — an alias for the current user

RequestWho sends it
GET /users/42an admin looks at any user
GET /users/mea regular user looks at themselves

me is a shortcut that the server expands into the ID from the authorization token. The client does not need to store its own userId separately.

When you need me. Ask yourself: "Could an administrator use this same endpoint with someone else's ID?" If yes — me is useful. A regular user passes me, an administrator passes a concrete ID.

GET /users/me           ✓ — an administrator could GET /users/42
GET /users/me/settings  ✓ — profile settings

When you don't need me. If the endpoint always works only with the caller's own data and there is no "look at someone else's" scenario, me adds noise without benefit:

GET /users/me/orders  ✗ — orders are already derived from the token, /orders is enough
GET /orders           ✓ — the current user sees only their own orders

One more constraint: me is an alias for a specific user in the users collection. A path /me without users/ in front of it makes no sense and should not be used.

GET /me         ✗ — unclear which resource it refers to
GET /users/me   ✓

me is used by the GitHub API, Google API, Spotify API, and Microsoft Graph — it is an established approach. Alternatives (self, current-user) are less common.

Temporal and ordinal aliases

To select the "edge" object from a collection, you can use alias words instead of long parameters:

RequestWhat it returns
GET /deployments/latestthe latest deployment — instead of ?sort=createdAt&order=desc&limit=1
GET /subscriptions/currentthe current subscription
GET /invoices/nextthe next invoice
GET /billing-periods/previousthe previous billing period

This works only for a singleton selection — when the context unambiguously identifies a single object. If there can be several such objects, you need ordinary filtering with parameters.

Logical aliases

A similar technique for objects singled out by a business attribute:

RequestWhat it returns
GET /payment-methods/defaultthe "default" payment method
GET /addresses/primarythe primary address
GET /plans/activethe active pricing plan
GET /documents/draftthe draft

Each of these is exactly one object, not a filtered list.

Action endpoints: domain commands

Some operations do not fit into CRUD. "Confirm an order" is neither a creation nor an update in the usual sense. It is a business command that has a name, side effects, and possibly input data.

For such cases you use an action endpoint: a resource plus an action verb.

POST /orders/{id}/confirm
POST /orders/{id}/cancel
POST /orders/{id}/ship
POST /orders/{id}/refund

What an action endpoint looks like

The path: a resource with an ID, then a verb in the infinitive.

The verb must be an infinitive, not a noun or a participle:

POST /orders/{id}/confirm      ✓
POST /orders/{id}/confirmation ✗ — a noun
POST /orders/{id}/confirmed    ✗ — a participle

The method is always POST. Even if the operation is technically idempotent (a repeated call produces the same result), you use POST. The reason is simple: an action is a command, not a replacement of a resource. PUT means "put this state here", POST means "perform this action". Semantics matter more.

Input data goes in the request body:

POST /orders/{id}/ship
Content-Type: application/json

{
  "trackingNumber": "TR-123456",
  "carrier": "DHL"
}

If there are no parameters, the body can be empty.

When to use an action, and when PATCH

A common dilemma: is changing an order's status a PATCH /orders/{id} with { "status": "CONFIRMED" } or a POST /orders/{id}/confirm?

The guideline is simple: if the operation has a domain name and side effects (events, state transitions, notifications) — it is an action. If it just changes a field value with no special logic — use PATCH.

PATCH /orders/{id} { "description": "..." }  ✓ — a simple field update
POST /orders/{id}/confirm                    ✓ — a domain command, a state machine
POST /orders/{id}/cancel                     ✓ — has a name, has side effects
PATCH /orders/{id} { "status": "CANCELLED" } ✗ — hides the domain meaning behind a field

Action endpoints make the API readable: the logs immediately show POST /orders/42/confirm rather than an abstract "order updated". Permission control is also simpler — each action gets its own permission.

Common mistakes

me where the endpoint works only with the current user's data. If there is no admin scenario with someone else's ID, me adds no meaning — it is just an extra segment.

/me without users/. me is an alias for a specific user inside the users collection, not a standalone path.

A noun or a participle in an action. /orders/{id}/confirmation looks like a resource, not a command. The correct form is /orders/{id}/confirm.

PUT for an action. PUT /orders/{id}/confirm is a semantic contradiction. PUT replaces a resource, POST performs a command.

A long action name. cancelTheOrderImmediately has redundant words. cancel is enough.

In short

  • An alias segment is a reserved word instead of an ID; the server expands it from context.
  • me is an alias for the current user; needed only when there is an admin scenario with someone else's ID. The path /me without users/ is not used.
  • Temporal aliases (latest, current, next, previous) are for a singleton selection of the edge object.
  • Logical aliases (default, primary, active, draft) are for an object singled out by a business attribute.
  • An action endpoint is for domain commands that have a name and side effects: resource + infinitive verb, method always POST.
  • Choosing between an action and PATCH: has a domain name and side effects → action; a simple field change → PATCH.