I'm looking for some best practices for "dry run" operations for REST APIs.
Say I have an endpoint that transfers money from account A to account B. I can initiate a transfer like so:
POST /transactions
{
"amount": 1000, // how much to transfer
"source": "A", // account to transfer from
"destination": "B" // account to transfer to
}
This action creates a "transaction", so the response would be a transaction object with payload containing:
{
"id": "txn-123",
"amount": 1000,
"source": "A",
"destination": "B",
"fees": 10, // any fees that were charged
"balance": 2500 // balance in source account AFTER transfer
}
I'd like to be able to perform a dry run for a couple reasons:
- to detrmine if the transfer will succeed (e.g. it may fail if there is a low balance in account A)
- to determine what the applicable fees would be beforehand
So, what is the best practice for a "dry run" concept? I can think of a few options:
- Pass a flag to the existing transfer endpoint to indicate a dry-run option. The flag could be a querystring, part of the payload, a header, etc. The exact implementation is up for debate, but conceptually I like this because it gives a clean interface to know all you have to know about performing a transfer from a single endpoint.
- Dedicated endpoint specifically for performing a transfer dry run. This "feels" safer because you don't inadvertently perform a destructive action since the live and dry-run endpoints are completely separate. On the other hand, you really should know what you're doing if you have access to a production system, so I'm not a huge fan.
- No dry-run concept. Just have a completely different set of endpoints to calculate fees, or get balance, or any other operation that helps you infer the outcome of a transfer. I don't like this because you're forcing the client to replicate all the logic that is already contained in the transfer endpoint.
These are my opinions on the matter so far, but I'd enjoy hearing other peoples' thoughts.