The lifecycle is your source of truth
After an approval, Reap emits the standard transaction webhooks:CARD_TRANSACTION_CREATED- a transaction is recorded for the first time.CARD_TRANSACTION_UPDATED- an existing transaction gains a new event (clearing, reversal, refund, or dispute refund).
events array is the authoritative record you reconcile against: every AUTHORIZATION, CLEARING, REVERSAL, REFUND, and DISPUTE_REFUND, each with its own amount. Post those to your ledger - they, not the authorization request, tell you what actually settled. The request only ever told you what you approved.
Reap also surfaces an aggregate amount breakdown (authorized, reversed, cleared, refunded, and the net current) computed over those same events. It is a convenient mirror of Reap’s own view - useful to cross-check your position against.
Correlate with the authorization request
ThetransactionId you received in the authorization request is the transaction id on every subsequent webhook. An incremental authorization carries the same transactionId as the first one, so you can attach the new reservation to a transaction you already hold.
The eventId appears again as triggerEventId and inside events. Use it to tie this reservation to the specific authorization event.
A decline is correlatable the same way. The transaction Reap records for it uses that transactionId and carries a DECLINE event under that same eventId. You can release the decision you logged without matching on amounts and timestamps.
Process events idempotently
Update your ledger as events arrive. Deliveries can repeat and are not guaranteed to arrive in order, so make your handling idempotent - key on the event id and skip anything you have already applied. Expect the settled amounts to differ from what you approved: partial clearings release the unused portion, over-clearings settle more than authorized, and reversals release the hold entirely. Release your provisional reservation and post the actual amounts as those events arrive. See the lifecycle for each scenario.Handle events with no prior authorization
Reap forwards every presentment the card network sends, including ones that never passed through your authorization endpoint. Your reconciliation must not assume a matching authorization always exists:- Offline and direct clearing. Transit gates and in-flight purchases clear without a real-time authorization. You receive
CARD_TRANSACTION_CREATEDwithstatus: CLEAREDand a singleCLEARINGevent - a charge with no hold to release. Book it as debt directly. - Standalone (unrelated) refund. A tax refund, goodwill credit, or a return long after the purchase arrives as
CARD_TRANSACTION_CREATEDwithstatus: CLEAREDand a singleREFUNDevent, with no preceding transaction. Credit the cardholder. - A clearing after a decline or reversal. The network can still present a clearing for a transaction you never approved or that was already reversed. Reap books it as debt; mirror the charge and reconcile.
These are the same edge cases Reap handles internally when it owns the ledger in Managed mode. In External mode the responsibility moves to you, which is why your ledger, not the authorization request, is the system of record.
Credit a dispute refund
A dispute that reachesREFUNDED credits the cardholder. The credit arrives on the disputed transaction as a DISPUTE_REFUND event in CARD_TRANSACTION_UPDATED. Post it the same way you post a REFUND: credit the cardholder the event’s amount, keyed on the event id. See Dispute refund.
The event’s amount equals the dispute’s refundedAmount. It is the refunded bill plus a prorated share of FX markup and ATM variable fee. It does not include the per-withdrawal ATM fixed fee, which stays charged. It can be less than the disputed amount. See How a refund is calculated.