Action-oriented APIs
Action-oriented APIs
In a typical REST API, the HTTP method carries all the meaning: POST creates, PUT updates, DELETE removes. The request body is an anonymous JSON payload shaped like the resource.
With commands, the request body is the action — a named, typed object that describes what the user intends to do.
A POST /orders that accepts a CreateOrderCommand is just as much a command as a POST /reports/:generate that accepts a GenerateReportCommand.
Creating an invoice is an action. Deleting a draft is an action. Generating a report is an action. Some map to standard REST verbs, some to custom routes — but they’re all commands. The difference isn’t in the URL style. It’s that every mutation has a class name, a UUID, and a paper trail.
What this gives you
- Named operations
-
The command log says
CreateOrderCommandorGenerateReportCommand, not "POST to /orders." You can query, monitor, and analyze by operation name. - Consistent contract
-
Every command carries
cmdUuidandcmdSourceRef. The structure is flat and form-friendly — it doesn’t need to mirror the domain model. - Works beyond HTTP
-
The same command class can be executed from a controller, a background job, a message handler, or a retry mechanism.
- Composable
-
One command can trigger others.
cmdSourceReflinks them — you can trace how a single user action propagated through the system.
Standard REST is fine
Not every endpoint needs a custom action-style route.
A POST /orders, DELETE /orders/{id}, or PATCH /orders/{id} are all commands — standard REST with a named, traceable body.
The command model adds value whenever the operation is worth recording — which, for state-changing operations, is most of the time.