Webhook events
Every event has this shape, and data depends on type:
{ id: string; type: WebhookEventType; data: … }id is stable across retries and replays, so deduplicate on it.
| Event | Sent when | Delivery |
|---|---|---|
credits.earned |
An earn was accepted, and is still pending | Best-effort |
credits.earn.confirmed |
The chain confirmed an earn | Exactly one per transaction is queued |
credits.redemption.confirmed |
The chain confirmed a spend, for checkout or a paid voucher | Exactly one per transaction is queued |
credits.reversed |
A confirmed earn or redemption was reversed | Queued with the reversal |
voucher.redeemed |
A voucher serial was used | Queued with the redemption |
Queued events can still be retried, so your receiver may see the same id more than once.
credits.earned
Section titled “credits.earned”An earn is on its way to the chain. Wait for credits.earn.confirmed before treating the points as spendable.
| Field | Type | Description |
|---|---|---|
transactionId |
string |
|
organizationEndUserId |
string |
|
purchaseAmount |
number |
|
estimatedPoints |
number |
An estimate, not the credited amount |
newBalance |
number |
Confirmed balance, which doesn’t include this earn yet |
credits.earn.confirmed
Section titled “credits.earn.confirmed”| Field | Type | Description |
|---|---|---|
transactionId |
string |
|
organizationEndUserId |
string |
|
pointsAmount |
number |
The amount actually credited on-chain |
newBalance |
number |
Confirmed balance right after this transaction |
blockchainDigest |
string |
credits.redemption.confirmed
Section titled “credits.redemption.confirmed”Has the same fields as credits.earn.confirmed, where pointsAmount is the amount debited.
credits.reversed
Section titled “credits.reversed”Settled in the ledger immediately. A chain-confirmed original is also mirrored on-chain afterwards, which sends no separate event.
| Field | Type | Description |
|---|---|---|
reversalTransactionId |
string |
|
reversedTransactionId |
string |
|
organizationEndUserId |
string |
|
pointsAmount |
number |
|
newBalance |
number |
|
balanceWentNegative |
boolean |
True when reversing a spent earn left a debt |
voucher.redeemed
Section titled “voucher.redeemed”No points move here. A paid claim already sent credits.redemption.confirmed for its cost.
| Field | Type | Description |
|---|---|---|
voucherOwnershipId |
string |
|
voucherId |
string |
|
organizationEndUserId |
string |
|
serialCode |
string |
|
status |
string |
REDEEMED |
redeemedAt |
string |
|
voucherTitle |
string |
|
discountType |
string |
|
discountValue |
string | null |

