Accept, return, freeze
Every deposit ends with one decision. You make it with one of three calls:
| Call | Decision | Meaning |
|---|---|---|
POST /casino/deposit/{id}/accept | accepted | Credit the player. The casino is settled for the deposit. |
POST /casino/deposit/{id}/return | returned | Send the crypto back to an address you give. |
POST /casino/deposit/{id}/freeze | frozen | Hold the funds pending regulatory guidance. |
A decision can be made only while the deposit's decision is pending. Once made, it
is final. The API has no call to change or undo a decision.
If two decision calls for the same deposit arrive at the same time, exactly one wins. The
other gets 409 with Cannot <action>: deposit decision is no longer 'pending' (already decided by a concurrent request). Nothing is written for the losing call.
Error bodies have a detail message and, for some errors, a code plus extra fields. The
format and the full list are on the Errors page.
Accept
POST https://quinix.byteconnect.us/casino/deposit/{id}/accept
The body is optional for an ordinary deposit. A restored late deposit requires the flag below.
| Field | Type | Required | Description |
|---|---|---|---|
adjust_to_received | boolean | For a mismatch or late deposit | Default false. Set true to accept at the amount actually received when it differs from the quote. Always required for a restored late deposit, even when amounts match. See Amount mismatches and Late payments. |
curl -X POST https://quinix.byteconnect.us/casino/deposit/4821/accept \
-H "X-API-Key: $API_KEY"
To send the flag:
curl -X POST https://quinix.byteconnect.us/casino/deposit/4821/accept \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"adjust_to_received": true}'
Do not send Content-Type: application/json with an empty body. The API rejects it with
400 Malformed JSON in request body. Either send no body and no content type, or send a
JSON object. adjust_to_received must be a JSON boolean: the string "true" is rejected.
When accept is allowed
The endpoint checks these gates. The first failing check decides the error.
-
Decision. The deposit's
decisionispending. -
Payment status. One of:
- the payment has at least one confirmation (
statusisConfirmed,ConfirmedApprovedorConfirmedKYTReview), or - the deposit is a fast deposit (
no_conforinstant), itsno_conf_stateiseligible, and it is paid but unconfirmed (Succeed,OverpaidorUnderpaid).
A fast deposit whose funding transaction was double-spent is never acceptable.
- the payment has at least one confirmation (
-
OFAC.
ofac_statusisclearortimed_out. This applies to instant deposits too. -
KYT.
kyt_statusispassed. Exception: an instant deposit may be accepted while KYT has not finished, if the market value of what arrived is within itsinstant_received_max_usd. Arevieworfailedresult always blocks. -
Amount and repricing. The received crypto equals the quote, or you sent
adjust_to_received: true. Every restored late deposit requires that flag and successful repricing at the current market rate.
The deposit's acceptable flag reports decision, payment and screening readiness. It does
not check the adjustment flag or whether late-payment repricing will succeed. See
The acceptable flag.
Amount mismatches
The player may send more or less than crypto_amount. Any difference counts, down to the
smallest unit (1e-8). While the deposit is unconfirmed, its status shows Overpaid or
Underpaid. At any time, compare confirmed_crypto with crypto_amount.
On a mismatch, /accept without the flag fails:
{
"detail": "Amount mismatch: quoted 0.0017517 BTC, received 0.0015 BTC. Send \"adjust_to_received\": true to accept at the actual received amount, or call /return to refund."
}
You then choose:
- Accept at the received amount. Call
/acceptwithadjust_to_received: true. - Return the funds. Call
/return.
With adjust_to_received: true, the deposit is re-priced from the crypto received:
- For an ordinary deposit, the rate is the one locked when the deposit was created. A restored late deposit uses the current market rate at acceptance instead.
- The fee and spread percents are the ones this deposit was quoted with. Changes to the casino's fee configuration since then are not applied.
- Every charge, the player amount and the casino's net are recomputed from the crypto received at the applicable rate, using the original fee and spread percentages.
The formulas are the crypto-mode formulas in Creating deposits.
After an adjusted accept, the player amount changes. Credit the player the player_amount
from the accept response or the deposit.accepted webhook, never the one from the create
response.
Late payments
A restored deposit marked late_payment: true requires adjust_to_received: true, even
when the received crypto equals the original quote. It is repriced at the current market rate.
The original quote is preserved in ByteFederal's records. Return is unchanged and still
follows its existing gates.
Without the flag, accept returns HTTP 400 with code: late_payment_requires_current_rate
and this exact detail:
Late payment: this deposit was paid after its quote expired. It can only be accepted at the current market rate: send "adjust_to_received": true to accept at the received amount re-priced now, or call /return to refund.
If the rate is unavailable, accept refuses with HTTP 502 late_payment_rate_unavailable;
retry later. It does not fall back to the original rate. If the received crypto cannot be
represented safely at the deposit's quote precision, accept refuses with HTTP 409
late_payment_received_precision; use return or contact ByteFederal.
Response
A 200 means the deposit is accepted. The response carries the final amounts. This
example is the deposit from Creating deposits, underpaid with
0.0015 BTC instead of 0.0017517 BTC and accepted with adjust_to_received: true:
{
"deposit_id": 4821,
"decision": "accepted",
"adjusted": true,
"crypto_amount": 0.0015,
"usd_amount": 88.2,
"player_amount": 85.631068,
"entity_net_usd": 84.77475728155339,
"affiliate_net_usd": 84.77475728155339,
"charges": [
{
"beneficiary": "AFFILIATE",
"kind": "FEE",
"paid_by": "PLAYER",
"percent": 0.03,
"amount_usd": 2.568932,
"amount_crypto": 0.00004369
},
{
"beneficiary": "BF",
"kind": "FEE",
"paid_by": "ENTITY",
"percent": 0.01,
"amount_usd": 0.856311,
"amount_crypto": 0.00001456
},
{
"beneficiary": "BF",
"kind": "SPREAD",
"paid_by": "PLAYER",
"percent": 0.02,
"amount_usd": 1.8,
"amount_crypto": 0.00003
}
],
"fee": 0,
"fee_usd": 0,
"bf_fee_usd": 0,
"bf_spread_usd": 1.8,
"affiliate_fee_usd": 2.568932,
"confirmed_crypto": 0.0015,
"crypto_rate": "58800"
}
| Field | Type | Description |
|---|---|---|
deposit_id | integer | The deposit. |
decision | string | Always accepted. |
adjusted | boolean | true if the deposit was re-priced to the received amount. |
crypto_amount | number | The final crypto amount, at the deposit's quote precision if adjusted. |
usd_amount | number | The final total paid by the player, in USD. |
player_amount | number | The final amount to credit the player, in USD. |
entity_net_usd | number | The final amount the casino is settled. |
charges | array | Every charge at its final amount. See Charges. |
confirmed_crypto | number or null | The crypto received on chain. |
crypto_rate | string or null | The rate used for acceptance, including spreads, as a decimal string. |
affiliate_net_usd, fee, fee_usd, bf_fee_usd, bf_spread_usd, affiliate_fee_usd | number | Deprecated aliases. Read entity_net_usd and charges. |
What accepting triggers
- A
deposit.acceptedwebhook with the final amounts. See the Webhook event reference. - A receipt for the player: an SMS with a receipt link to the player's phone, and an email when ByteFederal has an email address for the player.
- The deposit is included in the casino's settlement for
entity_net_usd.
These run after the response is sent. They never delay or fail the accept call.
Accept errors
| Status | code | detail |
|---|---|---|
| 400 | Invalid deposit ID | |
| 400 | Malformed JSON in request body | |
| 400 | Decision is already 'accepted', cannot accept (the quoted decision varies) | |
| 400 | Amount mismatch: quoted 0.0017517 BTC, received 0.0015 BTC. Send "adjust_to_received": true to accept at the actual received amount, or call /return to refund. | |
| 404 | Deposit not found | |
| 409 | Cannot accept: the funding transaction was double-spent before confirmation. | |
| 409 | Cannot accept: transaction status is 'Succeed' (not yet confirmed). Wait for confirmation. (standard deposit, paid but unconfirmed) | |
| 409 | Cannot accept: no-conf deposit is not eligible yet (state: pending_guards). Wait for guard evaluation or confirmation. (the state varies; pending when not yet set) | |
| 409 | Cannot accept: transaction status is 'Pending'. (any other status, for example unpaid or timed out) | |
| 409 | ofac_screen_pending | Cannot accept: OFAC screening has not completed yet. Wait for the ofac_complete webhook. Extra field ofac_deadline_at when the deadline is known. |
| 409 | ofac_sanctioned | Cannot accept: a funding address failed OFAC screening. The deposit is frozen; contact ByteFederal compliance. |
| 400 | late_payment_requires_current_rate | Late payment: this deposit was paid after its quote expired. It can only be accepted at the current market rate: send "adjust_to_received": true to accept at the received amount re-priced now, or call /return to refund. |
| 409 | late_payment_no_received_amount | Late payment has no confirmed received amount yet |
| 502 | late_payment_rate_unavailable | Unable to fetch <currency> rate or Unable to value <currency> at the current rate. Retry later; the currency is the deposit's ticker. |
| 409 | instant_received_over_cap | Cannot accept before KYT: received value $650.00 exceeds the instant received ceiling of $600.00. The deposit continues on the KYT-Fast path — wait for kyt_status 'passed'. Extra fields received_usd, instant_received_max_usd. |
| 409 | Cannot accept: KYT screening has not completed. Try again once kyt_status is 'passed'. | |
| 409 | Cannot accept: kyt_status is 'review', must be 'passed'. (also pending or failed) | |
| 409 | late_payment_received_precision | Received crypto cannot be represented safely at this asset's quote precision; call /return or contact ByteFederal |
| 409 | Cannot accept: deposit decision is no longer 'pending' (already decided by a concurrent request) | |
| 500 | Deposit charge ledger is invalid; contact ByteFederal | |
| 500 | Transaction has no market rate; cannot re-quote to the received amount | |
| 500 | Failed to accept deposit |
A 409 usually means "not yet". Wait for the next webhook for this deposit and check its
acceptable flag before calling again. For late_payment_received_precision, use return
or contact ByteFederal instead.
Return
POST https://quinix.byteconnect.us/casino/deposit/{id}/return
Send a JSON body with Content-Type: application/json. Without that header the API does
not read the body, and the return cannot be processed.
| Field | Type | Required | Description |
|---|---|---|---|
return_address | string | Yes | The address to send the crypto to, on the deposit's own chain. Must not be empty. |
reason | string | No | Free-text reason, kept with the return. If present it must not be empty. |
curl -X POST https://quinix.byteconnect.us/casino/deposit/4821/return \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"return_address": "bc1qexamplereturnaddress00000000000000000",
"reason": "Player cancelled the deposit"
}'
{
"deposit_id": 4821,
"decision": "returned",
"return_id": 317
}
| Field | Type | Description |
|---|---|---|
deposit_id | integer | The deposit. |
decision | string | Always returned. |
return_id | integer | The id of the queued return. The deposit.returned webhook carries it too. |
When return is allowed
All of these must hold:
- The deposit's
decisionispending. ofac_statusisclearortimed_out. Sanctioned funds can never be returned.kyt_statusispassed.- The payment
statusis exactlyConfirmed. confirmed_cryptois greater than zero.- No other return is already in progress for this deposit.
Only status: "Confirmed" qualifies. A fast deposit cannot be returned before it
confirms. A deposit whose status is ConfirmedKYTReview or ConfirmedApproved cannot be
returned through the API, even after its KYT review ends in passed. Such a deposit can
still be accepted. To return one, contact ByteFederal.
Check the address before you call
ByteFederal does not validate return_address when you call /return. The decision
becomes returned immediately and cannot be changed. If the address is wrong for the
chain or malformed, the return does not complete, and ByteFederal has to resolve it by
hand.
- Validate the address format for the deposit's currency before calling.
- For ETH, the address must be an ordinary account, not a contract. Returns to contract addresses are not supported and fail.
What happens on chain
- The full amount received (
confirmed_crypto) is sent toreturn_address. No fee or spread is deducted. ByteFederal pays the network fee. - ByteFederal's refund processor checks for queued returns every 5 minutes. For ETH, the return can take an extra step when the funds must first be moved from the deposit address.
- When the return transaction is broadcast, the payment
statuschanges toRefundand you receive atransaction.refundwebhook.
What returning triggers
- A
deposit.returnedwebhook right away, withreturn_id,return_addressandreason. - Later, the
transaction.refundwebhook described above, when the crypto is sent.
Return errors
| Status | code | detail |
|---|---|---|
| 400 | Invalid deposit ID | |
| 400 | Decision is already 'accepted', cannot return (the quoted decision varies) | |
| 400 | A validation body when return_address is missing or empty, or reason is empty. See the Errors page. | |
| 404 | Deposit not found | |
| 409 | ofac_screen_pending | Cannot return: OFAC screening has not completed yet. Wait for the ofac_complete webhook. |
| 409 | ofac_sanctioned | Cannot return: a funding address failed OFAC screening. The deposit is frozen; contact ByteFederal compliance. |
| 409 | Cannot return: KYT screening has not completed. Try again once kyt_status is 'passed'. | |
| 409 | Cannot return: kyt_status is 'review', must be 'passed'. (also pending or failed) | |
| 409 | Cannot return: transaction status is 'Succeed' (must be 'Confirmed') (the quoted status varies) | |
| 409 | Cannot return: confirmed_crypto is 0 (must be > 0) | |
| 409 | A return is already in progress for this transaction | |
| 409 | Cannot return: deposit decision is no longer 'pending' (already decided by a concurrent request) | |
| 500 | Failed to process return |
Freeze
POST https://quinix.byteconnect.us/casino/deposit/{id}/freeze
Freezing holds a deposit pending regulatory guidance. The deposit is neither credited nor returned. No body.
curl -X POST https://quinix.byteconnect.us/casino/deposit/4821/freeze \
-H "X-API-Key: $API_KEY"
{
"deposit_id": 4821,
"decision": "frozen"
}
When freeze is allowed
- The deposit's
decisionispending. kyt_statusispassed.
A deposit whose KYT has not finished, or is in review, cannot be frozen through the API.
What a frozen deposit means
- Accept, return and freeze are all refused with
400 Decision is already 'frozen', .... - The deposit is not included in the casino's settlement.
- There is no API call to unfreeze. ByteFederal compliance resolves frozen deposits outside the API. Contact ByteFederal to resolve one.
Automatic freezes
ByteFederal freezes a pending deposit itself in two cases:
- KYT screening returns
failed. - OFAC screening finds a sanctioned funding address (
ofac_status: "hit").
These automatic freezes do not send a deposit.frozen webhook. You learn about them
from the kyt_complete or ofac_complete webhook, and the deposit's decision reads
frozen.
What freezing triggers
A deposit.frozen webhook, for freezes made through this endpoint only.
Freeze errors
| Status | detail |
|---|---|
| 400 | Invalid deposit ID |
| 400 | Decision is already 'accepted', cannot freeze (the quoted decision varies) |
| 404 | Deposit not found |
| 409 | Cannot freeze: KYT screening has not completed. Try again once kyt_status is 'passed'. |
| 409 | Cannot freeze: kyt_status is 'review', must be 'passed'. (also pending or failed) |
| 409 | Cannot freeze: deposit decision is no longer 'pending' (already decided by a concurrent request) |
Webhook delivery for decisions
The deposit.accepted, deposit.returned and deposit.frozen webhooks are queued when
the decision is recorded and retried on failure. They go to the casino's webhook URL if one
is set, otherwise to your API key's webhook URL. No webhook is sent if neither is
configured. The decision itself is recorded either way. Payloads, signatures and retries
are described in Webhooks and the
Webhook event reference.