Skip to main content

Webhook event reference

This page lists every webhook event a casino integration receives, with a sample payload and its fields. For delivery, signatures, retries and idempotency, read Webhooks first.

EventFires whenProduced
deposit.receivedThe payment is seen on-chain (0 confirmations).Once per deposit
deposit.confirmedThe payment has at least one confirmation.Once per deposit
kyt_completeThe KYT screening result is set or changes.Once per kyt_result
ofac_completeThe OFAC screen of the funding addresses completes or misses its deadline.Once per ofac_result
double_spend_alertA zero-confirmation payment disappeared before confirming.Once per deposit
deposit.acceptedPOST /casino/deposit/{id}/accept succeeded.Once per deposit
deposit.returnedPOST /casino/deposit/{id}/return succeeded.Once per deposit
deposit.frozenPOST /casino/deposit/{id}/freeze succeeded.Once per deposit
transaction.<status>The underlying transaction's status changes.Once per status

"Produced once" does not mean "received once": the same delivery can arrive more than once, and events can arrive out of order. See Delivery guarantees.

Reading an event​

  • Casino events carry an event field with the event name. A body without an event field is a transaction.<status> event.
  • Check test first. It is present, and true, only on test events. Never credit a test event.
  • timestamp is the time the event was built, in Unix seconds. Retries keep the original value.
  • decision_at and double_spent_at are ISO 8601 timestamps in UTC.
  • market_rate and crypto_rate are decimal strings, so no precision is lost. Other amounts are JSON numbers.
  • The sample payloads below are real output of the API's payload builders for a synthetic $100 BTC deposit. They are shown pretty-printed; on the wire the body is compact.

Late payments​

A restored late deposit carries late_payment: true on every webhook event built after restoration, including transaction.<status> events. The boolean is present only when true and absent otherwise. Events for the restored deposit can arrive after transaction.timedout, when the player may already have been told it expired.

Check this field before accepting: a late deposit requires adjust_to_received: true and is repriced at the current market rate. See Late payments.

The acceptable field​

Casino deposit events carry acceptable; generic transaction.<status> events do not. It reports decision, payment and screening readiness when the event was built, including the instant ceiling valued at the deposit's recorded rate. It does not promise that an accept request will succeed.

Decide whether to accept from acceptable, not from decision, kyt_result or the event name. It is a snapshot, not a promise: a later change (a double-spend, a late KYT failure) can make accept fail, so keep handling 409 responses. Decision events always carry acceptable: false, because the deposit is already decided. See Accept, return, freeze.

acceptable does not check amount adjustments or late-payment repricing. A restored late deposit requires adjust_to_received: true even when the amounts match, and acceptance can still fail if it cannot be repriced.

A late accept uses the current market rate, which can put an instant deposit still waiting for KYT over its ceiling. Accept then returns 409 code instant_received_over_cap even if acceptable was true and the deposit's state has not changed. Wait for KYT to pass.

deposit.received​

Fires the first time the deposit's transaction reaches a status that means funds were received: Succeed, Underpaid or Overpaid, or any later status such as Confirmed. If a deposit moves straight to a confirmed status, you receive deposit.received and then deposit.confirmed.

Produced once per deposit.

What to do: show the player that the payment was detected. Check amount_matches: if it is false, the player sent a different amount than quoted, and accepting requires adjust_to_received (see Accept, return, freeze). Do not credit the player on this event. Accept only when an event carries acceptable: true.

The OFAC screen's deadline starts when this event is produced. ofac_complete follows.

{
"acceptable": false,
"address": "bc1qsampleaddressdonotsendfunds000000000",
"affiliate_fee_usd": 1.75,
"amount_matches": true,
"bf_fee_usd": 0,
"bf_spread_usd": 2.608975,
"charges": [
{
"amount_crypto": 0.00002609,
"amount_usd": 2.608975,
"beneficiary": "BF",
"kind": "SPREAD",
"paid_by": "PLAYER",
"percent": 0.025
},
{
"amount_crypto": 0.00001795,
"amount_usd": 1.75,
"beneficiary": "AFFILIATE",
"kind": "FEE",
"paid_by": "PLAYER",
"percent": 0.0175
}
],
"crypto_amount": 0.00104359,
"currency": "BTC",
"delta_crypto": 0,
"delta_usd_at_market": 0,
"deposit_id": 0,
"entity_external_code": "your-casino-code",
"entity_id": 1234,
"event": "deposit.received",
"fee": 0,
"fee_usd": 0,
"gambler_ref": "sample-player-001",
"instant": false,
"instant_downgraded": false,
"machine_id": null,
"market_rate": "100000.0000000000",
"no_conf": false,
"player_amount": 100,
"received_crypto": 0.00104359,
"test": true,
"timestamp": 1790172000,
"transaction_id": 0,
"usd_amount": 101.75
}

Deposit fields​

These fields appear on deposit.received and, where present, mean the same on every other event.

FieldTypeDescription
eventstringThe event name.
deposit_idnumberThe deposit's id. Use it with GET /casino/deposit/{id} and the decision endpoints.
transaction_idnumberThe id of the deposit's underlying transaction. It is the id of transaction.<status> events, as a string.
late_paymentbooleanPresent only when true on an event built after a late deposit is restored; absent otherwise. Also applies to transaction.<status> events.
entity_idnumberThe casino (entity) the deposit belongs to.
entity_external_codestring or nullThe casino's external code.
gambler_refstringYour reference for the player, as sent when the deposit was created.
currencystringThe cryptocurrency, for example BTC.
addressstringThe deposit address the player pays to.
crypto_amountnumberThe quoted crypto amount, or the final amount after an adjusted accept, at the deposit's quote precision.
usd_amountnumber or nullThe total USD the player pays: player_amount plus the fees the player pays. Spreads are part of the rate, not of this amount.
player_amountnumber or nullP: the USD amount the casino credits the player. null when usd_amount is null.
market_ratestring or nullThe market USD price per coin used for the amounts shown, before spreads. A late accept updates it to the rate used at acceptance.
chargesarrayEvery fee and spread booked against the deposit. See Charges.
fee, fee_usd, bf_fee_usd, bf_spread_usd, affiliate_fee_usdnumberDeprecated. See Deprecated charge fields.
no_confbooleanThe deposit was created for acceptance before its first confirmation.
instantbooleanThe deposit was created as an Instant deposit: it can be accepted before KYT completes, within the casino's limit.
instant_downgradedbooleanThe received value exceeded the Instant ceiling, so the deposit now waits for KYT passed like a standard deposit.
machine_idstring or nullThe machine identifier sent when the deposit was created.
acceptablebooleanDecision, payment and screening readiness when the event was built. See The acceptable field for its limits.
amount_matchesboolean or nulltrue when the received amount equals crypto_amount. null when no received amount is recorded.
delta_cryptonumber or nullReceived minus quoted crypto. Positive means overpaid, negative means underpaid.
delta_usd_at_marketnumber or nulldelta_crypto × market_rate, rounded to cents. null when either is unknown.
received_cryptonumber or nulldeposit.received only. The crypto amount received on-chain, as recorded when the event was built.
timestampnumberWhen the event was built, in Unix seconds.
testbooleanPresent only on test events, and then always true.

See Deposit lifecycle for zero-confirmation and Instant deposits.

Charges​

Each entry in charges is one fee or spread.

FieldTypeDescription
beneficiarystringWho earns the charge: BF (ByteFederal), AFFILIATE (BurraPay) or ENTITY (the casino).
kindstringFEE or SPREAD. A spread is built into the exchange rate.
paid_bystringPLAYER: added on top of player_amount. ENTITY: deducted from the casino's settlement.
percentnumberThe rate as a fraction: 0.025 is 2.5%.
amount_usdnumberThe charge in USD.
amount_cryptonumber or nullThe charge in crypto.

In the sample, the player is credited $100 (player_amount). The player pays a 1.75% BurraPay fee on top, so usd_amount is $101.75. ByteFederal's 2.5% spread is in the rate the player was quoted, so it does not add to usd_amount.

Deprecated charge fields​

These fields exist so older integrations keep working. They cannot describe every fee arrangement. Read charges instead.

FieldMeaning
feeByteFederal's player-paid fee, in crypto. 0 if none.
fee_usd, bf_fee_usdByteFederal's player-paid fee, in USD. The same value under two names. 0 if none.
bf_spread_usdByteFederal's spread, in USD. 0 if none.
affiliate_fee_usdBurraPay's player-paid fee, in USD. 0 if none.

deposit.confirmed​

Fires the first time the deposit's transaction reaches a status with at least one on-chain confirmation: Confirmed, ConfirmedKYTReview, ConfirmedApproved, Settled, Reimbursed or Refund.

Produced once per deposit.

What to do: for a standard deposit, confirmation is one of the conditions for accepting. KYT and OFAC must also pass. If acceptable is true, you can accept. KYT screening runs at confirmation, so kyt_complete usually follows.

The payload is the same as deposit.received, except that confirmed_crypto replaces received_crypto.

{
"acceptable": false,
"address": "bc1qsampleaddressdonotsendfunds000000000",
"affiliate_fee_usd": 1.75,
"amount_matches": true,
"bf_fee_usd": 0,
"bf_spread_usd": 2.608975,
"charges": [
{
"amount_crypto": 0.00002609,
"amount_usd": 2.608975,
"beneficiary": "BF",
"kind": "SPREAD",
"paid_by": "PLAYER",
"percent": 0.025
},
{
"amount_crypto": 0.00001795,
"amount_usd": 1.75,
"beneficiary": "AFFILIATE",
"kind": "FEE",
"paid_by": "PLAYER",
"percent": 0.0175
}
],
"confirmed_crypto": 0.00104359,
"crypto_amount": 0.00104359,
"currency": "BTC",
"delta_crypto": 0,
"delta_usd_at_market": 0,
"deposit_id": 0,
"entity_external_code": "your-casino-code",
"entity_id": 1234,
"event": "deposit.confirmed",
"fee": 0,
"fee_usd": 0,
"gambler_ref": "sample-player-001",
"instant": false,
"instant_downgraded": false,
"machine_id": null,
"market_rate": "100000.0000000000",
"no_conf": false,
"player_amount": 100,
"test": true,
"timestamp": 1790172000,
"transaction_id": 0,
"usd_amount": 101.75
}
FieldTypeDescription
confirmed_cryptonumber or nullThe crypto amount received on-chain, as recorded when the event was built.

Every other field is described under Deposit fields.

kyt_complete​

Fires when the KYT (Know Your Transaction) screening result for the deposit's funds is set, and again each time it changes to a new value, for example from review to passed after a manual compliance review.

Produced once per kyt_result value per deposit. If the result returns to a value that was already sent for the deposit, it is not sent again.

What to do depends on kyt_result:

kyt_resultMeaningWhat to do
passedThe funds passed screening.If acceptable is true, you can accept.
failedThe funds matched a blocking rule.If the deposit was still pending, ByteFederal froze it and decision is frozen. No deposit.frozen event is sent for this. If you already accepted the deposit (possible for Instant deposits), decision stays accepted; reverse the player's credit under your own policy.
reviewThe funds need a manual compliance review.Do not accept. decision stays pending, but acceptable is false and accept returns 409. Wait for another kyt_complete with the new result.
review looks actionable but is not

A review event carries decision: "pending", yet POST /casino/deposit/{id}/accept rejects the deposit with 409 until the result changes. Always decide from acceptable.

{
"acceptable": true,
"confirmed_crypto": 0.00104359,
"crypto_amount": 0.00104359,
"currency": "BTC",
"decision": "pending",
"deposit_id": 0,
"entity_external_code": "your-casino-code",
"entity_id": 1234,
"event": "kyt_complete",
"gambler_ref": "sample-player-001",
"instant": false,
"instant_downgraded": false,
"kyt_result": "passed",
"risk_score": 0,
"test": true,
"timestamp": 1790172000,
"transaction_id": 0,
"triggered_rules": []
}
FieldTypeDescription
kyt_resultstringpassed, failed or review.
risk_scorenumberThe risk score from the screening. Higher is riskier.
triggered_rulesarrayWhat the screening matched, as objects with ruleset (string or null), category and entity. Empty when nothing matched. Informational only; do not build logic on its contents.
decisionstringThe deposit's decision when the event was built: pending, accepted, returned or frozen.
confirmed_cryptonumber or nullThe crypto amount received on-chain, as recorded when the event was built.

kyt_complete does not carry address, usd_amount or charges. Every other field is described under Deposit fields.

ofac_complete​

Fires when the OFAC screen of the funding transaction's source addresses completes, or when it has not completed by its deadline. The deadline starts when deposit.received is produced.

Produced once per ofac_result value per deposit. Usually you receive a single clear. If the screen misses its deadline, you receive timed_out and later the real result.

What to do depends on ofac_result:

ofac_resultMeaningWhat to do
clearNo source address is sanctioned.The OFAC condition for accept and return is met. If acceptable is true, you can accept.
timed_outThe screen did not finish by its deadline.Accept and return are allowed anyway. The screen keeps running, and a second ofac_complete with clear or hit follows.
hitA source address is sanctioned.Accept and return are refused permanently (409, code ofac_sanctioned). If the deposit was pending, ByteFederal froze it and decision is frozen; no deposit.frozen event is sent. If you already accepted it (for example after timed_out), decision stays accepted; reverse the player's credit under your own policy.

The matched addresses are never included in the event.

{
"acceptable": true,
"confirmed_crypto": 0.00104359,
"crypto_amount": 0.00104359,
"currency": "BTC",
"decision": "pending",
"deposit_id": 0,
"entity_external_code": "your-casino-code",
"entity_id": 1234,
"event": "ofac_complete",
"gambler_ref": "sample-player-001",
"instant": false,
"instant_downgraded": false,
"ofac_result": "clear",
"test": true,
"timestamp": 1790172000,
"transaction_id": 0
}
FieldTypeDescription
ofac_resultstringclear, timed_out or hit.

decision and confirmed_crypto are described under kyt_complete. Every other field is described under Deposit fields.

double_spend_alert​

Fires for a zero-confirmation deposit (no_conf: true) that had become eligible for acceptance before confirmation, when its funding transaction disappears from the network before confirming and the address no longer holds the expected amount.

Produced once per deposit.

What to do: ByteFederal does not change the decision. If the deposit is still pending, do not accept it: acceptable is false and accept is refused from now on. If you already accepted it, you took the zero-confirmation risk for this deposit; reverse the player's credit under your own policy.

{
"acceptable": false,
"address": "bc1qsampleaddressdonotsendfunds000000000",
"crypto_amount": 0.00104359,
"currency": "BTC",
"decision": "pending",
"deposit_id": 0,
"double_spend_txid": "0000000000000000000000000000000000000000000000000000000000000000",
"double_spent_at": "2026-09-23T14:00:00.000Z",
"entity_external_code": "your-casino-code",
"entity_id": 1234,
"event": "double_spend_alert",
"gambler_ref": "sample-player-001",
"machine_id": null,
"test": true,
"timestamp": 1790172000,
"transaction_id": 0,
"usd_amount": 101.75
}
FieldTypeDescription
double_spend_txidstringThe id of the funding transaction that disappeared.
double_spent_atstring or nullWhen the double-spend was recorded (ISO 8601, UTC).
decisionstringThe deposit's decision, unchanged by the double-spend.
usd_amountnumberAs under Deposit fields.

Every other field is described under Deposit fields.

deposit.accepted​

Fires right after POST /casino/deposit/{id}/accept succeeds.

Produced once per deposit.

What to do: credit the player player_amount. The accept response returns the same amounts; this event matters most to a casino that receives events directly while BurraPay calls the API. If the deposit was accepted with adjust_to_received, adjusted is true and the amounts and charges are recalculated from the amount actually received. For a restored late deposit, acceptance uses the current market rate. See Late payments.

{
"acceptable": false,
"address": "bc1qsampleaddressdonotsendfunds000000000",
"adjusted": false,
"affiliate_fee_usd": 1.75,
"affiliate_net_usd": 100,
"bf_fee_usd": 0,
"bf_spread_usd": 2.608975,
"charges": [
{
"amount_crypto": 0.00002609,
"amount_usd": 2.608975,
"beneficiary": "BF",
"kind": "SPREAD",
"paid_by": "PLAYER",
"percent": 0.025
},
{
"amount_crypto": 0.00001795,
"amount_usd": 1.75,
"beneficiary": "AFFILIATE",
"kind": "FEE",
"paid_by": "PLAYER",
"percent": 0.0175
}
],
"confirmed_crypto": 0.00104359,
"crypto_amount": 0.00104359,
"crypto_rate": "97500.0000000000",
"currency": "BTC",
"decision": "accepted",
"decision_at": "2026-09-23T14:00:00.000Z",
"deposit_id": 0,
"entity_external_code": "your-casino-code",
"entity_id": 1234,
"entity_net_usd": 100,
"event": "deposit.accepted",
"fee": 0,
"fee_usd": 0,
"gambler_ref": "sample-player-001",
"instant": false,
"instant_downgraded": false,
"machine_id": null,
"no_conf": false,
"player_amount": 100,
"test": true,
"timestamp": 1790172000,
"transaction_id": 0,
"usd_amount": 101.75
}

Decision events share these fields:

FieldTypeDescription
decisionstringaccepted, returned or frozen, matching the event.
decision_atstring or nullWhen the decision was made (ISO 8601, UTC).
confirmed_cryptonumber or nullThe crypto amount received on-chain.
acceptablebooleanAlways false on decision events.

deposit.accepted adds:

FieldTypeDescription
adjustedbooleantrue when the deposit was accepted at the received amount (adjust_to_received).
crypto_ratestring or nullThe exchange rate used: market_rate less the spreads.
entity_net_usdnumber or nullWhat the casino is settled for this deposit, after any fees the casino pays.
affiliate_net_usdnumber or nullThe same value as entity_net_usd, under its older name. Use entity_net_usd.

Decision events do not carry market_rate, amount_matches, delta_crypto or delta_usd_at_market. Every other field is described under Deposit fields.

deposit.returned​

Fires right after POST /casino/deposit/{id}/return succeeds.

Produced once per deposit.

What to do: do not credit the player. The event means the return is queued, not sent. When the crypto is sent back on-chain, the transaction's status becomes Refund and you receive transaction.refund.

{
"acceptable": false,
"address": "bc1qsampleaddressdonotsendfunds000000000",
"affiliate_fee_usd": 1.75,
"bf_fee_usd": 0,
"bf_spread_usd": 2.608975,
"charges": [
{
"amount_crypto": 0.00002609,
"amount_usd": 2.608975,
"beneficiary": "BF",
"kind": "SPREAD",
"paid_by": "PLAYER",
"percent": 0.025
},
{
"amount_crypto": 0.00001795,
"amount_usd": 1.75,
"beneficiary": "AFFILIATE",
"kind": "FEE",
"paid_by": "PLAYER",
"percent": 0.0175
}
],
"confirmed_crypto": 0.00104359,
"crypto_amount": 0.00104359,
"currency": "BTC",
"decision": "returned",
"decision_at": "2026-09-23T14:00:00.000Z",
"deposit_id": 0,
"entity_external_code": "your-casino-code",
"entity_id": 1234,
"event": "deposit.returned",
"fee": 0,
"fee_usd": 0,
"gambler_ref": "sample-player-001",
"instant": false,
"instant_downgraded": false,
"machine_id": null,
"no_conf": false,
"player_amount": 100,
"reason": "Player cancelled the deposit",
"return_address": "bc1qsamplereturnaddressdonotsend0000000",
"return_id": 0,
"test": true,
"timestamp": 1790172000,
"transaction_id": 0,
"usd_amount": 101.75
}
FieldTypeDescription
return_idnumberThe id of the queued return.
return_addressstringThe address the crypto is returned to.
reasonstring or nullThe reason sent with the return request.

The shared decision fields are described under deposit.accepted; every other field under Deposit fields.

deposit.frozen​

Fires right after POST /casino/deposit/{id}/freeze succeeds, and only then. When ByteFederal freezes a deposit because KYT failed or OFAC found a sanctioned address, no deposit.frozen event is sent. That freeze shows as decision: "frozen" on kyt_complete or ofac_complete.

Produced once per deposit.

What to do: do not credit the player. The funds are held.

{
"acceptable": false,
"address": "bc1qsampleaddressdonotsendfunds000000000",
"affiliate_fee_usd": 1.75,
"bf_fee_usd": 0,
"bf_spread_usd": 2.608975,
"charges": [
{
"amount_crypto": 0.00002609,
"amount_usd": 2.608975,
"beneficiary": "BF",
"kind": "SPREAD",
"paid_by": "PLAYER",
"percent": 0.025
},
{
"amount_crypto": 0.00001795,
"amount_usd": 1.75,
"beneficiary": "AFFILIATE",
"kind": "FEE",
"paid_by": "PLAYER",
"percent": 0.0175
}
],
"confirmed_crypto": 0.00104359,
"crypto_amount": 0.00104359,
"currency": "BTC",
"decision": "frozen",
"decision_at": "2026-09-23T14:00:00.000Z",
"deposit_id": 0,
"entity_external_code": "your-casino-code",
"entity_id": 1234,
"event": "deposit.frozen",
"fee": 0,
"fee_usd": 0,
"gambler_ref": "sample-player-001",
"instant": false,
"instant_downgraded": false,
"machine_id": null,
"no_conf": false,
"player_amount": 100,
"test": true,
"timestamp": 1790172000,
"transaction_id": 0,
"usd_amount": 101.75
}

deposit.frozen has no fields of its own. The shared decision fields are described under deposit.accepted; every other field under Deposit fields.

transaction.<status>​

Fires when the deposit's underlying transaction moves to one of these statuses:

EventStatusMeaning
transaction.pendingPendingThe deposit was created and is waiting for payment.
transaction.succeedSucceedThe payment was seen on-chain for the quoted amount, not yet confirmed.
transaction.underpaidUnderpaidThe payment was seen on-chain for less than the quoted amount.
transaction.overpaidOverpaidThe payment was seen on-chain for more than the quoted amount.
transaction.confirmedConfirmedThe payment has at least one confirmation.
transaction.timedoutTimedoutNo payment was seen by expires_at, 30 minutes after creation. See Expiry and late payments.
transaction.cancelledCancelledThe transaction was cancelled before payment.
transaction.refundRefundThe crypto for a returned deposit was sent back on-chain.
transaction.settledSettledThe transaction was settled.

Other statuses, such as ConfirmedKYTReview, produce no transaction.<status> event. See Deposit lifecycle for every status.

Produced once per status per transaction, and only for the status seen when a worker polls. A status the transaction passes through between two polls produces no event. Treat these events as informational and build on the deposit.* events, which are never skipped this way.

How to recognize one: the body has no event field. It has id and status; the event name is transaction. followed by status in lowercase. It has no deposit_id. Match id to the transaction_id returned when the deposit was created, or carried on any casino event.

{
"cryptoAmount": 0.00104359,
"entity_external_code": "your-casino-code",
"id": "0",
"receivedCrypto": 0.00104359,
"status": "Confirmed",
"test": true,
"timestamp": 1790172000
}

Before any payment is seen, receivedCrypto is null:

{
"cryptoAmount": 0.00104359,
"entity_external_code": "your-casino-code",
"id": "0",
"receivedCrypto": null,
"status": "Pending",
"test": true,
"timestamp": 1790172000
}
FieldTypeDescription
idstringThe transaction id: the same number as transaction_id on casino events, as a string.
late_paymentbooleanPresent only when true on an event built after a late deposit is restored; absent otherwise.
statusstringThe new status, capitalized as in the table above.
cryptoAmountnumberThe quoted crypto amount, or the final amount after an adjusted accept, at the deposit's quote precision.
receivedCryptonumber or nullThe crypto amount received on-chain, as recorded when the event was built. null when nothing is recorded.
entity_external_codestring or nullThe casino's external code. snake_case, like on casino events.
timestampnumberWhen the event was built, in Unix seconds.
testbooleanPresent only on test events, and then always true.