You're adding in a layer of abstraction that is confusing
Your 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}/Deposit
AmountToDeposit=100, different parameters...
201 CREATED
Location=/card/123/account/456/Deposit/789
Now 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/789
204 NO CONTENT
The 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 Deposit
In 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}/Transaction
Amount=-100, different parameters...
201 CREATED
Location=/card/123/account/456/Transation/790
A 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.
I lean towards very simple, narrowly-focused endpoints. I would expect a request at some location like /sales_users which returns all sales users.
GET /sales_users:
[
{"id": 1, "name": "Anna Graham"},
{"id": 2, "name": "Dick Mussell"},
{"id": 3, "name": "Ford Parker"},
{"id": 4, "name": "Ferris Wheeler"},
{"id": 5, "name": "Jo King"}
]
Similarly, if you are going to have a list of categories, I would add a separate endpoint for that.
GET /categories:
[
{"id": 1, "name": "Category 1"},
{"id": 2, "name": "Category 2"},
{"id": 3, "name": "Category 3"},
{"id": 4, "name": "Category 4"},
{"id": 5, "name": "Category 5"}
]
I would not build a GET /product/new. Rather, I would build a form in your app to handle adding new products which knows the appropriate requests to populate its lists (e.g., GET /categories, GET /sales_users, etc.).
Best Answer
None of this is authoritative (as REST has no exact meaning). But from the original paper on REST a full (not ending in /) URL names a resource, while one ending in a slash '/' is a resource group (probably not worded like that).
A GET of a URL with a slash on the end is supposed to list the resources available.
A PUT on a URL with a slash is supposed to replace all the resources.
A DELETE on a URL with a slash is supposed to delete all the resources
A POST on a URL with a slash is supposed to create a new resource can then be subsequently accessed. To be conformant the new resource should be in this directory (though lots of RESTful architectures cheat here).
etc.
The wiki page on the subject seems to explain it well:
See example https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_Web_services.