Skip to main content

Errors

This page lists every error the Casino Deposits endpoints return, what causes each one, and what to do about it.

Error body​

Every error except validation errors and unknown paths returns JSON with one field, detail:

{
"detail": "Deposit not found"
}

detail is a human-readable message. Its wording can change. Do not parse it.

Some errors also carry a machine-readable code. When they do, code and any extra fields sit at the top level of the body, next to detail:

{
"detail": "Cannot create no-conf deposit: deposit 5821 has not reached its first on-chain confirmation yet. Wait for it to confirm (deposit.confirmed), or create this deposit without the fast flag.",
"code": "fast_deposit_unconfirmed",
"blocking_deposit_id": 5821,
"blocking_status": "Succeed"
}

Branch on code when it is present. The codes table lists every code and its extra fields.

Request ID​

Every response, success or error, carries an X-Request-ID header. If you send your own X-Request-ID header, the API echoes it back. Otherwise it generates a UUID.

The request ID is not in the JSON body. Log it with every error and include it when you contact ByteFederal about a failed call.

Unexpected server errors​

An unexpected failure returns HTTP 500 with a fixed message:

{
"detail": "Internal server error"
}

The real cause is logged on ByteFederal's side under the request ID.

Unknown paths​

A path that does not exist returns HTTP 404 with the plain-text body 404 Not Found, not JSON.

Validation errors​

When a request body or query string does not match the endpoint's schema, the API returns HTTP 400 with a different shape:

curl -X POST https://quinix.byteconnect.us/casino/deposit/5821/return \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"return_address": ""}'
{
"success": false,
"error": {
"name": "ZodError",
"message": "[\n {\n \"origin\": \"string\",\n \"code\": \"too_small\",\n \"minimum\": 1,\n \"inclusive\": true,\n \"path\": [\n \"return_address\"\n ],\n \"message\": \"Too small: expected string to have >=1 characters\"\n }\n]"
}
}

There is no detail field. error.message is a string that contains a JSON array of issues. Parse it a second time to read the issues. Each issue has a path (the field that failed) and a message.

Common causes:

  • A number sent as a string. "entity_id": "1234" fails; send "entity_id": 1234.
  • A missing required field.
  • A currency outside BTC, LTC, ETH, USDT, USDC.
  • "adjust_to_received": "true" (a string) on accept. Send the boolean true.

Malformed JSON​

A body that is not valid JSON, sent with Content-Type: application/json, returns:

{
"detail": "Malformed JSON in request body"
}

This includes an empty body. POST /casino/deposit/{id}/accept with Content-Type: application/json and no body returns this 400. Either send {} or leave out the Content-Type header.

Always send Content-Type: application/json with a body

If a request has a body but its Content-Type is not application/json, the API does not read the body at all. It treats the body as empty and the request fails later with a misleading error. For example, curl -d without -H "Content-Type: application/json" sends application/x-www-form-urlencoded, and POST /casino/integration/test-webhook then answers Unknown event 'undefined'.

Error codes​

These errors carry a code. Extra fields appear at the top level of the error body.

codeStatusEndpointExtra fields
fast_deposit_unconfirmed409POST /casino/deposit_addressblocking_deposit_id (number), blocking_status (string)
instant_over_cap400POST /casino/deposit_addressrequested_usd (number), instant_max_usd (number), instant_tier ("first" or "returning")
instant_received_over_cap409POST /casino/deposit/{id}/acceptreceived_usd (number), instant_received_max_usd (number)
ofac_screen_pending409POST /casino/deposit/{id}/accept, POST /casino/deposit/{id}/returnofac_deadline_at (ISO 8601 string), when a deadline is set
ofac_sanctioned409POST /casino/deposit/{id}/accept, POST /casino/deposit/{id}/returnnone
late_payment_requires_current_rate400POST /casino/deposit/{id}/acceptnone
late_payment_no_received_amount409POST /casino/deposit/{id}/acceptnone
late_payment_received_precision409POST /casino/deposit/{id}/acceptnone
late_payment_rate_unavailable502POST /casino/deposit/{id}/acceptnone

All other errors carry only detail.

Reading the tables​

The tables below give the exact detail text. Parts in angle brackets inside a message, such as <status>, are filled in with the real value.

Within each table, the 4xx errors are listed in the order the API checks them. A request that has several problems gets the first matching error.

Authentication​

These can occur on every authenticated endpoint. See Authentication.

StatusdetailCauseWhat to do
401Token or API key missingNo X-API-Key header (or other accepted credential) on the request.Send X-API-Key: $API_KEY.
401Invalid API key formatThe key contains a : but the part before it is not a number, or nothing follows it.Send the key exactly as ByteFederal issued it.
401Invalid API keyNo key matches.Check for truncation or whitespace. If it persists, ask ByteFederal to confirm the key.
401API key has expiredThe key's expiry has passed.Ask ByteFederal for a new key. GET /casino/integration/key shows expires_at before it happens.
401API key is inactive, API key is revokedThe key was deactivated or revoked.Ask ByteFederal for a new key.
403Affiliate account is disabled, Affiliate account is archivedYour partner account is switched off. Every key on it stops working.Contact ByteFederal.
401API key has no affiliate, Affiliate not found, Affiliate has no user, User not foundThe key's account setup is incomplete on ByteFederal's side.Contact ByteFederal with the request ID.
401Invalid or expired tokenA Bearer token was sent and it is invalid or expired.Casino integrations should use an API key.
401Token has been revokedA Bearer token was issued before its user's tokens were revoked.Log in again, or use an API key.
403Insufficient permissions for this endpointThe key has terminal scope. Every casino endpoint needs admin scope.Use an admin key. GET /casino/integration/key shows the key's scope.

Entity scope and entity status​

An API key is either affiliate-wide or locked to one entity (one casino). See Authentication.

StatusdetailEndpoint(s)CauseWhat to do
403API key is scoped to a different entityPOST /casino/deposit_address, GET /casino/deposits, POST /casino/integration/test-webhookThe key is locked to one entity and the request names another entity_id.Use the key issued for that entity, or an affiliate-wide key.
404Entity not found for this affiliatePOST /casino/deposit_address, GET /casino/deposits, POST /casino/integration/test-webhookThe entity_id does not exist or belongs to another partner.Check the entity id. GET /casino/integration/key lists the entities your key can use.
403Entity status is 'disabled', must be 'active' or 'enabled'POST /casino/deposit_address, GET /casino/depositsByteFederal has disabled the casino.Contact ByteFederal. Existing deposits can still be read by id and decided.
404Deposit not foundGET /casino/deposit/{id}, accept, return, freezeNo deposit with that id belongs to your account, or, for an entity-scoped key, to that key's entity.Check the deposit id and which key you are using.

A scoped key asking for another entity's deposit by id gets 404 Deposit not found, not 403.

Create a deposit​

POST /casino/deposit_address. See Creating deposits.

status: "kyc_required" and status: "kyc_pending" are not errors. They are HTTP 200 responses that mean the player must finish identity verification first. See Player KYC.

The KYC check runs before the checks below. For a player who has not finished KYC, you get kyc_required or kyc_pending even if the request would fail one of these checks.

StatusdetailCauseWhat to do
400validation error (see above)The body does not match the schema.Fix the field named in the issue's path.
503Identity verification service unavailableByteFederal could not check the player's identity status.Retry with backoff.
403Entity is not enabled for instant (pre-KYT) deposits — requires both entity.instant_allowed and entity.no_conf_allowedYou sent "instant": true and the casino is not set up for instant deposits.Send the deposit without instant, or ask ByteFederal to enable instant deposits for the casino.
403Entity is not enabled for no-conf deposits (entity.no_conf_allowed)You sent "no_conf": true (or "instant": true) and the casino is not set up for no-conf deposits.Send the deposit without the flag, or ask ByteFederal to enable it.
400<CURRENCY> is not enabledThe currency is switched off platform-wide.Use another currency.
400<CURRENCY> is not enabled for this affiliateThe currency is not enabled for your account.Use another currency, or ask ByteFederal to enable it.
502Unable to fetch <CURRENCY> rateNo exchange rate was available.Retry with backoff.
500Entity fee schedule is not configured for this entity; contact ByteFederalThe casino has no fee schedule in force.Contact ByteFederal. This is a setup problem on ByteFederal's side.
500Entity fee configuration is invalid; contact ByteFederalThe casino's fee schedule cannot be used.Contact ByteFederal.
400Instant deposits are capped at $<max> USD for a player's first deposit; requested $<total>. Create it without "instant" to use pre-confirmation-KYT acceptance instead. (or ...for a player's deposits after their first confirmed one; ...)code: instant_over_cap. The quoted total, fees included, is over the player's instant cap.Lower the amount, or create it without instant.
503Could not serialize fast deposit creation — try againAnother fast deposit for the same player was being created at the same moment.Retry once.
409Cannot create <instant|no-conf> deposit: deposit <id> 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.code: fast_deposit_unconfirmed. The player has an unpaid fast deposit whose quote has not expired.Wait for it to expire or be paid and confirmed, or create this one without no_conf / instant.
409Cannot create <instant|no-conf> deposit: deposit <id> has not reached its first on-chain confirmation yet. Wait for it to confirm (deposit.confirmed), or create this deposit without the fast flag.code: fast_deposit_unconfirmed. The player's previous fast deposit is paid but not yet confirmed. A player may have only one unconfirmed fast deposit at a time.Wait for deposit.confirmed on the blocking deposit, or create this one without the fast flag.
500Failed to create casino depositUsually no deposit address became available in time. The deposit may already exist: it is recorded before the address is assigned.Do not retry blindly. List the player's recent deposits with GET /casino/deposits first; see Creating deposits.

Read deposits​

GET /casino/deposit/{id} and GET /casino/deposits. See Reading deposits.

StatusdetailEndpointCauseWhat to do
400Invalid deposit IDGET /casino/deposit/{id}{id} does not start with a number.Send the numeric deposit_id.
400validation errorGET /casino/depositsentity_id is missing, or currency is not a supported currency.Add entity_id; fix currency.
400Invalid entity_idGET /casino/depositsentity_id is not a number.Send a numeric entity id.

The entity scope and entity status errors above also apply.

Accept​

POST /casino/deposit/{id}/accept. See Accept, return, freeze.

The deposit's acceptable field reports decision, payment and screening readiness. It does not check amount adjustments or late-payment repricing. A restored late deposit still requires adjust_to_received: true, and a failed rate lookup returns 502. See Late payments.

StatusdetailCauseWhat to do
400Malformed JSON in request bodyContent-Type: application/json with an empty or invalid body.Send {} or a valid body.
400validation erroradjust_to_received is not a boolean.Send true or false, not a string.
400Invalid deposit ID{id} does not start with a number.Send the numeric deposit_id.
404Deposit not foundSee above.
400Decision is already '<decision>', cannot acceptThe deposit was already accepted, returned or frozen.Read the deposit. If decision is accepted, an earlier accept succeeded; treat it as done.
409Cannot accept: the funding transaction was double-spent before confirmation.A no-conf deposit's payment was double-spent. It can never be accepted.Do not credit the player. See double_spend_alert in Webhook events.
409Cannot accept: transaction status is '<status>' (not yet confirmed). Wait for confirmation.A standard deposit is paid but not yet confirmed on chain.Wait for deposit.confirmed.
409Cannot accept: no-conf deposit is not eligible yet (state: <state>). Wait for guard evaluation or confirmation.A no-conf deposit is paid but has not passed its pre-confirmation checks.Wait until acceptable is true.
409Cannot accept: transaction status is '<status>'.The deposit is not in a state that can be accepted, for example unpaid (Pending) or expired.Read the deposit to see its status. See Deposit lifecycle.
409Cannot accept: a funding address failed OFAC screening. The deposit is frozen; contact ByteFederal compliance.code: ofac_sanctioned.Do not credit the player. Contact ByteFederal compliance.
409Cannot accept: OFAC screening has not completed yet. Wait for the ofac_complete webhook.code: ofac_screen_pending.Wait for the ofac_complete webhook. ofac_deadline_at says when the wait ends at the latest.
400Late 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.code: late_payment_requires_current_rate. Accept was requested for the restored late deposit without adjust_to_received: true.Send {"adjust_to_received": true} to accept at the current market rate, or return it subject to the return gates.
409Late payment has no confirmed received amount yetcode: late_payment_no_received_amount. No finite, positive confirmed received amount is available for the late deposit.Read the deposit and contact ByteFederal if the amount remains unavailable.
502Unable to fetch <currency> rate or Unable to value <currency> at the current ratecode: late_payment_rate_unavailable. The current rate or resulting valuation is unavailable or invalid.Retry later. The API never falls back to the expired quote.
409Cannot accept before KYT: received value $<received> exceeds the instant received ceiling of $<ceiling>. The deposit continues on the KYT-Fast path — wait for kyt_status 'passed'.code: instant_received_over_cap. An instant deposit received more than its ceiling, so it must wait for KYT.Wait for kyt_complete with a passed result.
409Cannot accept: KYT screening has not completed. Try again once kyt_status is 'passed'.KYT has not produced a result yet.Wait for the kyt_complete webhook.
409Cannot accept: kyt_status is '<kyt_status>', must be 'passed'.KYT is still pending, or its result is review or failed.For review, wait: ByteFederal reviews it and a new kyt_complete follows. For failed, do not credit the player.
400Amount mismatch: quoted <quoted> <CURRENCY>, received <received> <CURRENCY>. Send "adjust_to_received": true to accept at the actual received amount, or call /return to refund.The player sent a different amount than quoted.Accept again with {"adjust_to_received": true}, or return the deposit.
409Received crypto cannot be represented safely at this asset's quote precision; call /return or contact ByteFederalcode: late_payment_received_precision. The late accept would round to zero crypto or credit more crypto than was received.Return the deposit subject to the return gates, or contact ByteFederal.
409Cannot accept: deposit decision is no longer 'pending' (already decided by a concurrent request)Another accept, return or freeze for the same deposit won the race.Read the deposit to see the decision that was recorded.
500Underlying transaction not found, Deposit charge ledger is invalid; contact ByteFederal, Transaction has no market rate; cannot re-quote to the received amountData problem on ByteFederal's side.Contact ByteFederal with the request ID.
500Failed to accept depositThe accept could not be written. Nothing was recorded.Read the deposit. If decision is still pending, retry.

Return​

POST /casino/deposit/{id}/return. See Accept, return, freeze.

StatusdetailCauseWhat to do
400validation errorreturn_address is missing or empty, or reason is an empty string.Send a non-empty return_address. Leave reason out rather than sending "".
400Invalid deposit ID{id} does not start with a number.Send the numeric deposit_id.
404Deposit not foundSee above.
400Decision is already '<decision>', cannot returnThe deposit was already accepted, returned or frozen. A deposit that fails KYT is frozen automatically, so it lands here too.Read the deposit. If decision is returned, an earlier return succeeded.
409Cannot return: a funding address failed OFAC screening. The deposit is frozen; contact ByteFederal compliance.code: ofac_sanctioned. Funds from a sanctioned address can never be returned.Contact ByteFederal compliance.
409Cannot return: OFAC screening has not completed yet. Wait for the ofac_complete webhook.code: ofac_screen_pending.Wait for the ofac_complete webhook.
409Cannot return: KYT screening has not completed. Try again once kyt_status is 'passed'.KYT has not produced a result yet.Wait for kyt_complete.
409Cannot return: kyt_status is '<kyt_status>', must be 'passed'.KYT is pending or under review.Wait for a passed kyt_complete.
409Cannot return: transaction status is '<status>' (must be 'Confirmed')The deposit is not confirmed on chain yet, or its status has moved past Confirmed.Wait for deposit.confirmed. For any other status, contact ByteFederal.
409Cannot return: confirmed_crypto is <amount> (must be > 0)No received amount is recorded.Contact ByteFederal.
409A return is already in progress for this transactionA return was already queued for this deposit.Do not send another.
409Cannot return: deposit decision is no longer 'pending' (already decided by a concurrent request)Another decision for the same deposit won the race.Read the deposit.
500Failed to process returnThe return could not be written. Nothing was queued.Read the deposit. If decision is still pending, retry.

Freeze​

POST /casino/deposit/{id}/freeze. See Accept, return, freeze.

StatusdetailCauseWhat to do
400Invalid deposit ID{id} does not start with a number.Send the numeric deposit_id.
404Deposit not foundSee above.
400Decision is already '<decision>', cannot freezeThe deposit was already decided.Read the deposit.
409Cannot freeze: KYT screening has not completed. Try again once kyt_status is 'passed'.KYT has not produced a result yet. Freeze needs a passed KYT result.Wait for kyt_complete.
409Cannot freeze: kyt_status is '<kyt_status>', must be 'passed'.KYT is pending, under review, or failed.Wait for a passed kyt_complete.
409Cannot freeze: deposit decision is no longer 'pending' (already decided by a concurrent request)Another decision won the race.Read the deposit.

Integration tools​

See Testing your integration.

StatusdetailEndpointCauseWhat to do
400This endpoint describes an API key. Authenticate with the X-API-Key header.GET /casino/integration/keyThe request used a Bearer token, not an API key.Call it with X-API-Key.
404API key not foundGET /casino/integration/keyThe key's record could not be loaded.Contact ByteFederal with the request ID.
400validation errorPOST /casino/integration/test-webhookentity_id is missing or not a positive integer, or event is missing.Fix the body.
400Unknown event '<event>'. See the webhook reference for valid event names.POST /casino/integration/test-webhookevent is not a webhook event name.Use a name from Webhook events.
403API key is scoped to a different entityPOST /casino/integration/test-webhookSee above.
404Entity not found for this affiliatePOST /casino/integration/test-webhookSee above.
409No webhook URL is configured for this entityPOST /casino/integration/test-webhookNeither the casino nor any active API key that covers the casino has a webhook URL.Ask ByteFederal to set one.
429Rate limit exceeded. Try again in <n> seconds.POST /casino/integration/test-webhookMore than 10 calls in the current window. See Rate limits.Wait Retry-After seconds.

The test webhook returns HTTP 200 even when your endpoint fails. Check delivered in the response.

Rate limits​

Only POST /casino/integration/test-webhook is rate limited. It allows 10 calls per 60-second window per API key. The window starts with the first call and resets 60 seconds later.

Every call counts, including calls that fail validation or are refused because the key is scoped to a different entity. Calls rejected for authentication, or because the key's scope is not admin, do not count.

Every response from that endpoint carries these headers:

HeaderMeaning
X-RateLimit-LimitCalls allowed per window (10).
X-RateLimit-RemainingCalls left in the current window.
X-RateLimit-ResetWhen the window resets, as a Unix timestamp in seconds.

The 429 response adds Retry-After, in seconds:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1790346887

{"detail":"Rate limit exceeded. Try again in 60 seconds."}

Retrying safely​

Retry 502 and 503 with backoff.

Do not blindly retry 500 Failed to create casino deposit. The deposit may already exist without an address, and a retry creates a second one (or, for a fast deposit, is refused with fast_deposit_unconfirmed). Check the player's recent deposits first.

For a failed accept or return, read the deposit before retrying. If a response was lost after the API recorded the decision, a retry returns 400 Decision is already '<decision>'. That is the signal the first call worked.

Do not retry a 409 in a loop. Most 409s clear when a webhook arrives (deposit.confirmed, ofac_complete, kyt_complete). Wait for the webhook, or for acceptable: true.