I'm in the process of designing an HTTP API, hopefully making it as RESTful as possible.There are some actions which functionality spreads over a few resources, and sometime needs to be undone.I thought to myself, this sounds like a command pattern, but how can I model it into a resource?I will introduce a new resource named XXAction, like DepositAction, which will be created through something like thisPOST /card/{card-id}/account/{account-id}/DepositAmountToDeposit=100, different parameters...this will actually create a new DepositAction and activate it's Do/Execute method.In this case, returning a 201 Created HTTP status means the action has been executed successfully.Later if a client wishes to look at the action details he canGET /action/{action-id}Update/PUT should be blocked I guess, because it is not relevant here.And in order to Undo the action, I thought of usingDELETE /action/{action-id}which will actually call the Undo method of the relevant object, and change it's status.Let's say I'm happy with only one Do-Undo, I don't need to Redo.Is this approach ok?Are there any pitfalls, reasons not to use it?Is this understood from the POV of the clients?
Implementing the command pattern in a RESTful API
design patterns;api;rest;api design;http
You're adding in a layer of abstraction that is confusingYour API starts off very clean and simple. A HTTP POST creates a new Deposit resource with the given parameters. Then you go off the rails by introducing the idea of actions that are an implementation detail rather than a core part of the API.As an alternative consider this HTTP conversation...POST /card/{card-id}/account/{account-id}/DepositAmountToDeposit=100, different parameters...201 CREATED Location=/card/123/account/456/Deposit/789Now you want to undo this operation (technically this should not be allowed in a balanced accounting system but what the hey):DELETE /card/123/account/456/Deposit/789204 NO CONTENTThe API consumer knows that they are dealing with a Deposit resource and is able to determine what operations are permitted on it (usually through OPTIONS in HTTP).Although the implementation of the delete operation is conducted through actions today there is no guarantee that when you migrate this system from, say, C# to Haskell and maintain the front end that the secondary concept of an action would continue to add value, whereas the primary concept of Deposit certainly does.Edit to cover an alternative to DELETE and DepositIn order to avoid a delete operation, but still effectively remove the Deposit you should do the following (using a generic Transaction to allow for Deposit and Withdrawal):POST /card/{card-id}/account/{account-id}/TransactionAmount=-100, different parameters...201 CREATED Location=/card/123/account/456/Transation/790A new Transaction resource is created which has exactly the opposite amount (-100). This has the effect of balancing the account back to 0, negating the original Transaction. You might consider creating a utility endpoint like POST /card/{card-id}/account/{account-id}/Transaction/789/Undo    <- BAD!to get the same effect. However, this breaks the semantics of a URI as being an identifier by introducing a verb. You are better off sticking to nouns in identifiers and keeping operations constrained to the HTTP verbs. That way you can easily create a permalink from the identifier and use it for GETs and so on.