Treat it as a high-availability, low-latency service
Authorization fails closed: if you time out, return a non-2xx, return an unparseable body, or are unreachable, Reap declines the transaction and the cardholder sees a decline at the terminal. There is no retry on the live transaction.
- Budget your entire round trip - network, decoding, signature check, your decision, and encoding - to comfortably fit inside the 1.6 second window.
- Run the endpoint with redundancy and autoscaling. A cold start or a single slow dependency during a traffic spike declines real transactions.
- Monitor decline-by-timeout and error rates as a first-class SLO. A rise there is lost cardholder spend, not just noise.
Verify every request
Reap signs each request with your endpoint’s signing secret. Before you trust any field in the body, verify the signature over the exact raw request bytes - not the re-serialized JSON. Reject anything that fails verification with a non-2xx (which fails closed to a decline). This is the same scheme as your other webhooks, so you can reuse that verification code.
Decide fast and deterministically
Reap has already applied card state, spend policies, and platform limits before calling you, so your endpoint does not re-implement those. Your job is the money decision: does this cardholder have the balance, and do your own risk controls allow it? Keep the decision path to cheap, local reads and writes:- Read the cardholder’s available balance from your own ledger and compare against
amount. - Apply only controls and checks you can evaluate within the latency budget.
- Keep slow or best-effort work — analytics, notifications, and any dependency you cannot bound — off the decision path, or behind a hard timeout that fails to a safe default well inside your budget. Never let an optional dependency block the response.
INSUFFICIENT_BALANCE, TRANSACTION_NOT_ALLOWED); everything else is decided by Reap before you are called.
Reserve funds atomically when you approve
An approval is a commitment: Reap relays it to the network and a hold is placed. Multiple authorizations for the same card can arrive concurrently, so guard your balance the way Reap guards its own ledger - place the reservation atomically at the moment you approve, so two in-flight authorizations cannot both pass the balance check and overdraw. Reserve the authorizedamount, and treat that reservation as provisional. The final settled amount frequently differs from what you approved:
- A partial clearing settles less than authorized and releases the remainder.
- An over-clearing (tips, fuel, hotel incidentals) settles more than authorized.
- A reversal releases the hold entirely.
The request is not your record
The authorization request is the live decision point and nothing more. It does not tell you whether the transaction ultimately cleared, was reversed, or was refunded, and it is not durable. Your ledger’s source of truth is the asynchronous transaction lifecycle that follows an approval. Correlate the two witheventId.