Skip to main content

Creating deposits

A deposit starts with one call: POST /casino/deposit_address. You send the player, the currency and the amount. ByteFederal checks the player's KYC, prices the deposit from the casino's fee configuration, and returns an address and the exact crypto amount to pay.

POST https://quinix.byteconnect.us/casino/deposit_address

Request​

Send a JSON body with the header Content-Type: application/json.

warning

The Content-Type: application/json header is required. Without it the body is not read at all: the API treats it as empty and skips validation. The request then fails with an error that does not describe the real problem.

FieldTypeRequiredDescription
entity_idintegerYesThe casino's entity id. It must belong to your affiliate. An entity-scoped key may only use its own entity.
currencystringYesBTC, LTC or ETH. Upper case. The currency must be enabled for your affiliate.
gambler_refstringYesYour stable reference for the player. KYC status is kept per casino and gambler_ref, so reuse the same value for the same player. Keep it to 255 characters or fewer.
phonestringYesThe player's phone number. KYC links are sent to it by SMS. Required on every call, including for players who have already passed KYC.
emailstring or nullNoThe player's email address. Must be a valid email address if present. When it is supplied, the player's receipt is also sent by email.
amountnumberYesMust be greater than zero. By default this is the USD amount the player wants credited. See Amounts.
amount_is_cryptobooleanNoDefault false. When true, amount is the amount of crypto the player will send.
no_confbooleanNoDefault false. Asks for pre-confirmation acceptance. See Fast deposits.
instantbooleanNoDefault false. Asks for instant (pre-KYT, pre-confirmation) acceptance. Implies no_conf. See Fast deposits.
machine_idstringNoYour machine or kiosk identifier, at most 64 characters. It is echoed on deposit reads and on webhooks.

Types are strict. entity_id must be a JSON number, not a string. no_conf, instant and amount_is_crypto must be JSON booleans.

Obsolete fields​

Older integrations sent player_amount, affiliate_fee and total_amount. These fields are accepted and discarded. They have no effect on the price. Fees always come from the casino's fee configuration held by ByteFederal. Remove them from new code.

Example​

curl -X POST https://quinix.byteconnect.us/casino/deposit_address \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entity_id": 1234,
"currency": "BTC",
"gambler_ref": "sample-player-001",
"phone": "+15551234567",
"email": "[email protected]",
"amount": 100,
"machine_id": "kiosk-042"
}'

Responses​

Every successful call returns HTTP 200. Branch on the status field. It is one of ok, kyc_required or kyc_pending.

KYC is checked first. If the player is not verified, no deposit is created and no address is issued.

ok: deposit created​

{
"status": "ok",
"deposit_id": 4821,
"transaction_id": 90312,
"gambler_ref": "sample-player-001",
"address": "bc1qexampledepositaddress000000000000000",
"currency": "BTC",
"crypto_amount": 0.0017517,
"usd_amount": 103,
"player_amount": 100,
"entity_net_usd": 99,
"affiliate_net_usd": 99,
"crypto_rate": 58800,
"market_rate": 60000,
"fee": 0,
"fee_usd": 0,
"bf_fee_usd": 0,
"bf_spread_usd": 2.1020399999999997,
"affiliate_fee_usd": 3,
"charges": [
{
"beneficiary": "BF",
"kind": "SPREAD",
"paid_by": "PLAYER",
"percent": 0.02,
"amount_usd": 2.1020399999999997,
"amount_crypto": 0.00003503
},
{
"beneficiary": "AFFILIATE",
"kind": "FEE",
"paid_by": "PLAYER",
"percent": 0.03,
"amount_usd": 3,
"amount_crypto": 0.00005102
},
{
"beneficiary": "BF",
"kind": "FEE",
"paid_by": "ENTITY",
"percent": 0.01,
"amount_usd": 1,
"amount_crypto": 0.00001701
}
],
"expires_at": "2026-09-25T15:30:00.000Z"
}

The example uses an illustrative fee configuration: a 2% ByteFederal spread, a 3% BurraPay fee paid by the player, and a 1% ByteFederal fee paid by the casino. The market rate is $60,000. The numbers were produced by the API's own pricing code.

FieldTypeDescription
statusstringok.
deposit_idintegerThe deposit's id. Use it for every later call and to match webhooks.
transaction_idintegerThe id of the underlying payment. Webhooks carry it too.
gambler_refstringEcho of the request.
addressstringThe address the player pays. Reads call this field wallet.
currencystringEcho of the request.
crypto_amountnumberThe exact amount of crypto the player must send, rounded to at most 8 decimal places.
usd_amountnumberWhat the player pays in total, in USD: the player amount plus every fee the player pays.
player_amountnumberThe amount to credit the player, in USD.
entity_net_usdnumberWhat the casino is settled for this deposit, after any fees the casino pays.
affiliate_net_usdnumberDeprecated. The same value as entity_net_usd.
crypto_ratenumberThe USD price per coin the player is quoted: market_rate less all spreads.
market_ratenumberThe market price per coin at quote time, before spreads.
chargesarrayEvery fee and spread on this deposit. See Charges.
fee, fee_usd, bf_fee_usd, bf_spread_usd, affiliate_fee_usdnumberDeprecated. Partial views of charges, kept for older integrations. They cannot represent every charge. Read charges instead.
expires_atstringISO 8601 UTC time the quote expires, 30 minutes after creation. ByteFederal honors a payment until then. Show the player a 15-minute window, not this time: read Expiry and late payments.

Money values in this response are not rounded. Round them only for display. Values read back later from GET /casino/deposit/{id} are stored values and can differ in the last digits (for example 2.10204 instead of 2.1020399999999997).

kyc_required and kyc_pending​

{
"status": "kyc_required",
"message": "Identity verification required. A verification link has been sent."
}
{
"status": "kyc_pending",
"message": "Identity verification is pending. Please complete verification to proceed."
}

The player has not passed KYC. ByteFederal sends the player a link by SMS. Show the player the message and ask them to complete verification, then call this endpoint again. The full flow and every message value are on the KYC page.

Amounts​

USD mode (default)​

amount is the player amount: the USD value you will credit the player. Fees the player pays are added on top. Spreads are applied to the rate.

crypto_rate = market_rate × (1 − sum of spread percents)
usd_amount = amount × (1 + sum of player-paid fee percents)
crypto_amount = usd_amount ÷ crypto_rate
player_amount = amount

Crypto mode (amount_is_crypto: true)​

amount is the crypto the player will send, fees included. The player amount is derived from it.

crypto_amount = amount, rounded to at most 8 decimal places
usd_amount = crypto_amount × crypto_rate
player_amount = usd_amount ÷ (1 + sum of player-paid fee percents)

Minimum and maximum​

No minimum deposit is enforced today. amount only has to be greater than zero. Instant deposits have a per-player cap, described below. There is no other maximum in the API.

Charges​

Each deposit carries a list of charges. A charge is one fee or spread, earned by one party and paid by one party. You never send fees. They come from the casino's fee configuration, which ByteFederal sets up with BurraPay per casino.

FieldTypeDescription
beneficiarystringWho earns the charge: BF (ByteFederal), AFFILIATE (BurraPay) or ENTITY (the casino).
kindstringSPREAD or FEE.
paid_bystringPLAYER or ENTITY.
percentnumberThe configured rate as a fraction. 0.02 is 2%.
amount_usdnumberThe charge in USD.
amount_cryptonumber or nullThe charge in the deposit's currency.

How each kind works:

  • Spread (kind: "SPREAD"). Always paid by the player. It lowers the rate the player gets. Its amount_usd is crypto_amount × market_rate × percent, so a 2% spread is 2% of the market value of the crypto sent, which is slightly more than 2% of usd_amount.
  • Player-paid fee (kind: "FEE", paid_by: "PLAYER"). A percent of the player amount, added on top of it.
  • Casino-paid fee (kind: "FEE", paid_by: "ENTITY"). A percent of the player amount, deducted from the casino's settlement. It does not change what the player pays.

The casino's settlement is:

entity_net_usd = player_amount
+ the casino's own player-paid fee
+ the casino's own spread
− casino-paid fees

In the example: 100 + 0 + 0 − 1 = 99.

Only charges with a percent above zero appear in the list.

note

Credit the player player_amount. If the player pays a different amount than quoted, the deposit is re-priced when you accept it, and the accept response carries the final player_amount. See Accept, return, freeze.

Fast deposits​

By default a deposit can be accepted only after it has one on-chain confirmation and has passed KYT screening. Two flags make it acceptable sooner. Both must be enabled for the casino by ByteFederal.

FlagAcceptable whenRequires
no_conf: trueBefore confirmation, once ByteFederal's pre-confirmation checks mark it eligible and KYT has passed.The casino enabled for no-conf deposits.
instant: trueBefore confirmation and before KYT completes, within the player's instant cap.The casino enabled for both instant and no-conf deposits.

instant: true always implies no_conf: true.

Instant caps​

An instant deposit has two limits, both set per casino by ByteFederal:

  • Quote cap. Checked at creation against usd_amount (what the player pays, including player-paid fees). The default is $500 for a player's first deposit and $1,500 once the player has an earlier deposit with this casino that was accepted and confirmed on chain. Over the cap, creation fails with code instant_over_cap.
  • Received ceiling. Checked at accept against the market value of what actually arrived. The default is $600 for a first deposit and $1,600 for a returning player. If the player overpays past it, the deposit stops being instant and waits for KYT to pass. Reads show this as instant_downgraded: true.

The tier is decided when the deposit is created and does not change afterwards.

One fast deposit at a time​

A player can have only one fast (no_conf or instant) deposit in flight with a casino. Another fast deposit is refused while an earlier one is either:

  • unpaid, not yet timed out, and not yet past its expires_at, or
  • paid but not yet confirmed on chain.

The refusal is a 409 with code fast_deposit_unconfirmed. Standard deposits are never blocked by this rule. You can create the new deposit without the fast flags instead.

Errors​

Errors other than schema validation return a JSON body with a detail message. Some also carry a machine-readable code and extra fields at the top level. Branch on code where one exists. The full error reference is on the Errors page.

Schema validation failures (a missing field, a wrong type, an unknown currency) return 400 with a different body (abbreviated here):

{
"success": false,
"error": {
"name": "ZodError",
"message": "[\n {\n \"code\": \"invalid_value\", ... \"path\": [\n \"currency\"\n ], ... }\n]"
}
}

error.message is a JSON-encoded string listing each problem and the path of the field.

Errors specific to this endpoint:

StatuscodedetailMeaning
400BTC is not enabled for this affiliateThe currency is not enabled for your affiliate. The ticker varies.
400BTC is not enabledThe currency is switched off for everyone. The ticker varies.
400instant_over_capInstant deposits are capped at $500.00 USD for a player's first deposit; requested $515.00. Create it without "instant" to use pre-confirmation-KYT acceptance instead.The quote is over the player's instant cap. Extra fields: requested_usd, instant_max_usd, instant_tier (first or returning). For a returning player the text reads for a player's deposits after their first confirmed one.
403API key is scoped to a different entityAn entity-scoped key used another entity_id.
403Entity status is 'disabled', must be 'active' or 'enabled'The casino is switched off.
403Entity is not enabled for instant (pre-KYT) deposits — requires both entity.instant_allowed and entity.no_conf_allowedinstant: true on a casino not enabled for it.
403Entity is not enabled for no-conf deposits (entity.no_conf_allowed)no_conf: true on a casino not enabled for it.
404Entity not found for this affiliateThe entity_id does not exist under your affiliate.
409fast_deposit_unconfirmedCannot create instant deposit: deposit 4820 is an open fast-deposit quote (unpaid, not yet expired). Wait for it to confirm (deposit.confirmed), or create this deposit without the fast flag.See One fast deposit at a time. Extra fields: blocking_deposit_id, blocking_status. The text says no-conf instead of instant for a no-conf request, and has not reached its first on-chain confirmation yet when the blocking deposit is already paid.
500Entity fee schedule is not configured for this entity; contact ByteFederalThe casino has no fee configuration in force.
500Entity fee configuration is invalid; contact ByteFederalThe casino's fee configuration is invalid.
500Failed to create casino depositSee the warning below.
502Unable to fetch BTC rateNo market rate was available. Retry. The ticker varies.
503Could not serialize fast deposit creation — try againA concurrent fast-deposit request for the same player held the lock. Retry.
503Identity verification service unavailableThe KYC check could not run. Retry.

Example instant_over_cap body:

{
"detail": "Instant deposits are capped at $500.00 USD for a player's first deposit; requested $515.00. Create it without \"instant\" to use pre-confirmation-KYT acceptance instead.",
"code": "instant_over_cap",
"requested_usd": 515,
"instant_max_usd": 500,
"instant_tier": "first"
}
warning

A 500 Failed to create casino deposit does not always mean nothing was created. When no pre-generated address is available, the API waits up to 30 seconds for a new one after the deposit is recorded. If that wait fails, you get this 500, but the deposit already exists without an address you can show the player. If the failed request was a fast deposit, that deposit blocks a new fast deposit for the same player until its expires_at passes or it is paid. List the player's recent deposits with GET /casino/deposits if you need to reconcile.

Authentication errors (401, 403 for a key without admin scope) are covered on the Authentication page.

What happens next​

The deposit is created with status: "Pending" and decision: "pending". From here, webhooks tell you when the payment is seen, confirmed and screened. When a deposit's acceptable flag is true, you can accept it. See: