Skip to main content

Deposit lifecycle

A deposit moves along three independent tracks. Your integration watches all three.

TrackFieldValuesWho changes it
PaymentstatusPending, Succeed, Underpaid, Overpaid, Confirmed, …ByteFederal's payment engine, as the blockchain moves
Decisiondecisionpending, accepted, returned, frozenYou (accept, return, freeze), or ByteFederal on a screening failure
Screeningkyt_status, ofac_statusKYT: passed, review, failed. OFAC: clear, hit, timed_outByteFederal's screening

You never have to combine these yourself to decide when to accept. The acceptable flag does that for you.

Transaction status​

status is the payment state of the deposit's underlying transaction. It appears on deposit reads (GET /casino/deposit/{id}) and in the generic transaction.<status> webhooks. Values are case-sensitive strings, exactly as shown.

StatusMeaning
PendingWaiting for payment. Nothing has arrived at the address yet.
SucceedThe exact quoted amount has been seen on-chain. Not yet confirmed.
UnderpaidLess than the quoted amount has been seen on-chain. Not yet confirmed.
OverpaidMore than the quoted amount has been seen on-chain. Not yet confirmed.
TimedoutNothing arrived by the deposit's expires_at, 30 minutes after creation. See Expiry and late payments.
CancelledThe deposit was cancelled while still unpaid.
ConfirmedThe payment reached its required confirmations: 1 for BTC and LTC, 12 blocks for Ethereum assets.
ConfirmedKYTReviewConfirmed, and KYT returned review or failed. ByteFederal compliance handles it.
ConfirmedApprovedConfirmed. The accept gate treats it the same as Confirmed.
PendingSettlementAccepted and being settled to the casino.
SettledSettled to the casino.
RefundYou returned the deposit and the refund has been sent on-chain.

An underpaid or overpaid deposit still confirms. It becomes Confirmed once the amount that did arrive reaches the required confirmations. The deposit webhooks tell you the difference in amount_matches, delta_crypto and delta_usd_at_market.

Events: what fires when​

Every event below is a webhook sent to your webhook URL. Payloads are documented in Webhook events.

EventFires whenCarries acceptable
transaction.pendingThe deposit is created.No
deposit.receivedFunds are first seen on-chain (status becomes Succeed, Underpaid or Overpaid).Yes
transaction.succeed, transaction.underpaid, transaction.overpaidStatus becomes that value.No
ofac_completeThe OFAC screen of the funding addresses finishes, or misses its deadline (ofac_result: clear, hit or timed_out). Fires again if the result changes.Yes
kyt_completeKYT finishes (kyt_result: passed, review or failed). Fires again if the result changes, for example review to passed after compliance review.Yes
deposit.confirmedThe payment reaches its required confirmations (status becomes Confirmed or a later status).Yes
transaction.confirmedStatus becomes Confirmed.No
double_spend_alertA no-conf deposit's funding transaction disappeared before it confirmed.Always false
deposit.acceptedYou called accept and it succeeded.Always false
deposit.returnedYou called return and it succeeded.Always false
deposit.frozenYou called freeze and it succeeded.Always false
transaction.refundStatus becomes Refund (the return has been sent on-chain).No
transaction.settledStatus becomes Settled.No
transaction.timedoutStatus becomes Timedout.No
transaction.cancelledStatus becomes Cancelled.No

Rules that hold for every deposit:

  • transaction.<status>, deposit.received and deposit.confirmed are each sent at most once per deposit.
  • deposit.received always arrives before deposit.confirmed. No other ordering is guaranteed. kyt_complete and ofac_complete come from separate workers and can arrive before or after deposit.confirmed.
  • ByteFederal detects status changes by polling. If a deposit passes through a status between two polls, no transaction.<status> event is sent for that status. deposit.received and deposit.confirmed are still sent, because they are derived from where the deposit ends up.
  • ConfirmedKYTReview, ConfirmedApproved and PendingSettlement have no transaction.<status> event. You see them on reads, and you learn about KYT through kyt_complete.
  • There is no deposit.frozen event when ByteFederal freezes a deposit. A KYT failure arrives as kyt_complete with kyt_result: "failed" and decision: "frozen". An OFAC hit arrives as ofac_complete with ofac_result: "hit".

Typical order​

A standard deposit, paid in full, usually produces:

  1. transaction.pending
  2. deposit.received, transaction.succeed
  3. ofac_complete (clear)
  4. deposit.confirmed, transaction.confirmed
  5. kyt_complete (passed, acceptable: true)
  6. You call accept. deposit.accepted
  7. Later, transaction.settled

For a no-conf or instant deposit, kyt_complete and acceptable: true can arrive before step 4. See Deposit levels.

Decision​

decision records what happens to the funds. Every deposit starts at pending. It leaves pending exactly once, and there is no API to move it again.

DecisionSet byWhat happens next
pendingDeposit creationWaiting for you (or for screening).
acceptedPOST /casino/deposit/{id}/acceptThe deposit is credited and settled to the casino.
returnedPOST /casino/deposit/{id}/returnByteFederal sends the received crypto to your return address. Status later becomes Refund.
frozenPOST /casino/deposit/{id}/freeze, or ByteFederal when KYT fails or OFAC hitsFunds are held. Contact ByteFederal to resolve it.

ByteFederal freezes only a deposit whose decision is still pending. If you already accepted an instant deposit and a later KYT or OFAC result is bad, the decision stays accepted. You receive kyt_complete (failed) or ofac_complete (hit) with decision: "accepted". That event is your signal to reverse the player's credit. The same applies to double_spend_alert on an accepted no-conf deposit.

Screening: KYT and OFAC​

ByteFederal screens every deposit twice. You do not run either screen yourself.

KYT​

KYT (Know Your Transaction) scores the risk of the funds' on-chain history. It runs when a standard deposit confirms, or before confirmation for a no-conf or instant deposit.

kyt_status on readskyt_result in kyt_completeMeaningEffect
null or pendingnot sentNot finished.Accept waits, except for instant deposits within their ceiling.
passedpassedClean.Accept, return and freeze are allowed (subject to the other gates).
reviewreviewNeeds manual compliance review.Accept is blocked. Status becomes ConfirmedKYTReview. You receive kyt_complete again when review finishes.
failedfailedBlocking risk found.A pending deposit is frozen. Status becomes ConfirmedKYTReview.

OFAC​

The OFAC screen checks the addresses that funded the deposit against the sanctions list. It starts as soon as the payment is seen. It has a deadline of 15 seconds after deposit.received is sent. If the screen has not finished by then, the deposit proceeds as timed_out and the screen keeps running.

ofac_status on readsofac_result in ofac_completeMeaningEffect
pendingnot sentScreen running, deadline not reached.Accept and return are refused with 409 code ofac_screen_pending.
clearclearNo sanctioned address.Accept and return are allowed.
timed_outtimed_outDeadline passed before the screen finished.Accept and return are allowed. A second ofac_complete follows with the final result.
hithitA funding address is sanctioned.A pending deposit is frozen. Accept and return are refused forever with 409 code ofac_sanctioned.
warning

A timed_out screen can later turn into hit. If you accepted in between, you receive ofac_complete with ofac_result: "hit" and decision: "accepted". Reverse the player's credit and contact ByteFederal compliance.

The matched addresses are never sent to partners. The result is the whole signal.

The acceptable flag​

acceptable is a snapshot of the deposit's decision, payment and screening readiness for acceptance. It does not promise that an accept request will succeed.

Key your accept logic on it. On any webhook that carries acceptable: true, you may call accept. The same rule works for standard, no-conf and instant deposits. You do not need to track which screen each level waits for.

acceptable uses the decision, payment and screening checks below. It is true only when all of these hold:

  1. decision is pending.

  2. The payment state allows it. Either:

    • status is Confirmed, ConfirmedApproved or ConfirmedKYTReview, or
    • status is Succeed, Overpaid or Underpaid, the deposit is no-conf, and no_conf_state is eligible.

    A no-conf deposit whose funding transaction was double-spent (no_conf_state: "double_spent") is never acceptable, whatever its status.

  3. ofac_status is clear or timed_out.

  4. kyt_status is passed. Or: the deposit is instant, KYT has not finished (null or pending), and the received value is within the deposit's instant ceiling.

acceptable appears on:

  • GET /casino/deposit/{id} and GET /casino/deposits, computed at read time.
  • deposit.received, deposit.confirmed, kyt_complete and ofac_complete, computed when the event was built.
  • deposit.accepted, deposit.returned, deposit.frozen and double_spend_alert, where it is always false.

It is not on the generic transaction.<status> events.

Four things to know:

  • It is a snapshot. State can change between the webhook and your accept call. A double-spend or a late KYT failure closes the gate again. Keep handling 409 from accept. The next webhook carries the new value.
  • It can become true without a webhook. No event fires when a no-conf deposit becomes eligible. If the last webhook for a deposit said false and you are still waiting, read the deposit with GET /casino/deposit/{id}.
  • It does not check amount adjustments or late-payment repricing. If the received amount differs from the quote (amount_matches: false), accept returns 400 unless you send "adjust_to_received": true. A restored late deposit requires that flag even when the amounts match, and acceptance can still fail if it cannot be repriced. See Decisions.
  • A late instant accept revalues the ceiling. Readiness uses the deposit's recorded rate. Acceptance uses the current market rate for a restored late deposit, 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 levels: standard, no-conf and instant​

You choose the level per deposit with the no_conf and instant flags on create. ByteFederal must enable a level for your casino before you can use it.

StandardNo-confInstant
Request flagsnone"no_conf": true"instant": true (implies no-conf)
Earliest acceptAfter confirmationBefore confirmation, once eligibleBefore confirmation, once eligible
KYT needed before acceptYes, passedYes, passedNo, if within the instant ceiling
OFAC needed before acceptclear or timed_outclear or timed_outclear or timed_out
Size limitnonenonePer-player quote cap and received ceiling
Double-spend risknoneYoursYours

Standard​

The default. Accept opens after the payment confirms, OFAC is clear or timed_out, and KYT is passed. KYT runs at confirmation, so kyt_complete is usually the event that carries acceptable: true.

No-conf​

Accept can open before the first confirmation.

After the payment is seen, ByteFederal checks the funding transaction. no_conf_state on reads shows the result:

no_conf_stateMeaning
nullNot evaluated yet.
pending_guardsBeing evaluated.
eligibleCan be accepted before confirmation. KYT runs now.
fell_backNot eligible. The deposit follows the standard flow and becomes acceptable after confirmation. An eligible BTC or LTC deposit that is still unconfirmed after 24 hours also falls back.
double_spentThe funding transaction disappeared before confirming. Never acceptable. You receive double_spend_alert.

Once eligible, the deposit becomes acceptable when KYT passes and OFAC is clear or timed_out. kyt_complete (passed) is usually the event that carries acceptable: true.

warning

You carry the double-spend risk on a no-conf or instant deposit you accept before confirmation. If the funding transaction disappears afterwards, the decision stays accepted. You receive double_spend_alert and must reverse the player's credit yourself.

Instant​

Instant goes one step further than no-conf: accept can open before KYT finishes. It still waits for no-conf eligibility and for OFAC clear or timed_out. A completed review or failed KYT result always blocks accept.

Instant deposits have two limits. ByteFederal sets both per casino.

  • Quote cap. Checked at create. If the quoted total is over the cap, create fails with 400 code instant_over_cap. Create the deposit without instant instead. The cap has two tiers: one for a player's first deposit, and a higher one once the player has an accepted, confirmed deposit with your casino. The error body's instant_tier field (first or returning) tells you which tier applied.
  • Received ceiling. Checked against what actually arrives, valued at the quote's market rate for ordinary deposits. A late accept uses the current market rate instead. The ceiling is fixed when the deposit is created. Reads show it as instant_received_max_usd.

At deposit.received, the received value is evaluated at the deposit's recorded rate. If it is over the ceiling, for example because the player overpaid, instant_downgraded becomes true. A pending deposit then waits for KYT passed like a no-conf deposit. The event already carries instant_downgraded: true when that excess is visible at that point.

A late accept separately checks the ceiling at the current market rate. An over-ceiling refusal returns 409 code instant_received_over_cap and does not set instant_downgraded; wait for KYT to pass before accepting.

If KYT later fails on an instant deposit you already accepted, the decision stays accepted. You receive kyt_complete with kyt_result: "failed" and must reverse the player's credit.

One fast deposit per player​

A player can have only one no-conf or instant deposit in flight at a time. Create returns 409 code fast_deposit_unconfirmed while the player's previous fast deposit:

  • is paid but not yet confirmed, or
  • is an unpaid quote that has not timed out, which means its expires_at has not passed.

The error body's blocking_deposit_id field names the deposit that blocks. Standard deposits are never blocked. You can always create the deposit without the fast flags instead.

Expiry and late payments​

A deposit's quote is locked when it is created. The response carries expires_at, 30 minutes after creation.

Show the player a 15-minute payment window. ByteFederal keeps watching the address and honors a payment until expires_at, 30 minutes after creation. The extra 15 minutes are a grace period for players who are slow or have trouble paying. A payment that arrives in that grace period is credited like any other.

If nothing has arrived by expires_at, the status becomes Timedout and the quote expires.

danger

A deposit paid after it expired is not restored automatically. ByteFederal is alerted internally. Support can restore an eligible deposit after verifying the payment.

If a player pays after expires_at, contact ByteFederal with the deposit_id and the on-chain transaction id.

Late payments​

After support restores a deposit, its new webhook events and its single-deposit and list reads carry late_payment: true. The boolean is present only when true and absent otherwise. Events for a restored deposit can arrive after transaction.timedout; the player may already have been told the deposit expired.

A restored late deposit can be accepted only with adjust_to_received: true, at the current market rate. The original quote is preserved in ByteFederal's records. Return is unchanged and still follows its existing gates.

The expires_at limit applies only to a deposit where nothing has arrived. Once any amount is seen (Succeed, Underpaid or Overpaid), the deposit continues to confirmation, however long that takes.

Each deposit address is used once. Never show a player the address of an earlier deposit. Create a new deposit instead.

For ordinary deposits, the quote's market rate stays locked. If the received amount differs and you accept with "adjust_to_received": true, the amounts are recalculated at the rate locked at creation. Restored late deposits use the current market rate at acceptance instead.