The four events
A single state change produces two deliveries: the broad
refund.updated and the specific refund.successful or
refund.failed.
Deliveries are queued, so they can arrive out of order, and
refund.created can reach you before your POST /v1/refunds call
returns. Decide from data.status, not from which event landed
first.
Payload
The envelope is the standard webhook envelope.data is the Refund
object, exactly as
GET /v1/refunds/{refundUid} returns it.
refund.successful
refund.updated is the only refund event that carries
changed_fields, a map of each changed key to its previous value.
Together with data it gives you both sides of the transition:
Failures
Onrefund.failed, error tells you whether a retry is worth it.
Related events
A refund also moves money on the payment, so expectugwo.activity.updated and ugwo.updated alongside the refund
events whenever refunded_amount or a status changes. See what a
refund does to the
payment.
Handling refunds safely
- Acknowledge fast. Verify
X-Kwugwo-Signature, queue the event, return200. A slow handler burns one of your three delivery attempts. - Deduplicate on the envelope
uid. Retries reuse it. Note thatrefund.updatedandrefund.successfuldescribe the same transition under different envelope IDs, so dedupe protects you from replays, not from the two-event pattern. - Make the effect idempotent on
data.uid. Key your bookkeeping on the refund ID so a credit happens once, however many events mention it. - Re-fetch before anything expensive.
datais a snapshot from when the event fired; pullGET /v1/refunds/{uid}if your worker runs later. - Accept unfamiliar refunds. Refunds created outside the
API arrive with
ref: nullfor refunds you never requested. Record them.
Node (Express)