Skip to main content

Testing your integration

There is no sandbox. The API at https://quinix.byteconnect.us runs on mainnet.

You can test two things without moving money:

  1. Check your API key: what the key is, which casinos it can act on, and where each casino's webhooks go.
  2. Send a test webhook: one signed sample event, delivered to the casino's configured webhook URL.

Everything else needs a real deposit. See the mainnet walkthrough.

Production is mainnet

Every deposit address is a real mainnet address. Every deposit moves real crypto. Every return sends real crypto to the address you give. Test with small amounts and with wallets you control.

Check your API key​

GET /casino/integration/key describes the key you call it with. It never returns secrets.

curl https://quinix.byteconnect.us/casino/integration/key \
-H "X-API-Key: $API_KEY"

Response for an affiliate-wide key:

{
"key": {
"id": 77,
"name": "production",
"mode": "live",
"scope": "admin",
"expires_at": "2027-09-01T00:00:00.000Z"
},
"affiliate": {
"id": 42,
"name": "Example Partner"
},
"entity_scope": null,
"entities": [
{
"id": 1234,
"name": "Example Casino",
"external_code": "your-casino-code",
"status": "enabled",
"webhook": {
"url": "https://casino.example.com/webhooks/byteconnect",
"signed": true,
"source": "entity_override"
}
},
{
"id": 1235,
"name": "Second Casino",
"external_code": null,
"status": "disabled",
"webhook": {
"url": "https://partner.example.com/webhooks/byteconnect",
"signed": true,
"source": "api_key"
}
}
]
}

A key locked to one casino returns that casino in entity_scope and lists only that casino in entities:

{
"key": {
"id": 77,
"name": "production",
"mode": "live",
"scope": "admin",
"expires_at": "2027-09-01T00:00:00.000Z"
},
"affiliate": {
"id": 42,
"name": "Example Partner"
},
"entity_scope": {
"id": 1234,
"name": "Example Casino"
},
"entities": [
{
"id": 1234,
"name": "Example Casino",
"external_code": "your-casino-code",
"status": "enabled",
"webhook": {
"url": "https://casino.example.com/webhooks/byteconnect",
"signed": true,
"source": "entity_override"
}
}
]
}
FieldTypeDescription
key.idnumberThe key's id. Quote it to ByteFederal when asking about the key.
key.namestring or nullThe key's label.
key.mode"live" or "test"See Test mode.
key.scope"admin" or "terminal"Casino endpoints need admin. A terminal key gets 403 on this endpoint too.
key.expires_atstring or nullISO 8601 UTC. null means the key does not expire.
affiliateobjectYour partner account: id and name.
entity_scopeobject or nullThe one casino the key is locked to (id, name), or null for an affiliate-wide key.
entities[]arrayEvery casino the key can act on, in any status, ordered by id.
entities[].idnumberThe entity_id to send in requests.
entities[].namestringThe casino's name.
entities[].external_codestring or nullThe code that appears as entity_external_code in webhook payloads.
entities[].statusstringenabled or disabled. Deposits can only be created for an enabled casino.
entities[].webhookobject or nullWhere this casino's webhooks are delivered. null means no webhook URL is configured and no webhooks are sent.
entities[].webhook.urlstringThe delivery URL.
entities[].webhook.signedbooleantrue when deliveries carry X-Webhook-Signature. false means they are sent unsigned.
entities[].webhook.sourcestringentity_override: the casino's own webhook setting. api_key: the webhook URL on an active API key that covers this casino. A key locked to this casino wins over an affiliate-wide key. It is not necessarily the key you called with.

Look for three things:

  • The casino you expect is listed, with status: "enabled".
  • webhook.url is where you expect events to arrive: the casino's own endpoint (entity_override) or BurraPay's (api_key).
  • webhook.signed is true.

Send a test webhook​

POST /casino/integration/test-webhook sends one sample event to the webhook URL configured for a casino and reports how your endpoint answered.

curl -X POST https://quinix.byteconnect.us/casino/integration/test-webhook \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"entity_id": 1234, "event": "deposit.accepted"}'
FieldTypeRequiredDescription
entity_idintegerYesThe casino whose configured webhook URL receives the event. Any status, so you can test before the casino is enabled.
eventstringYesThe event to send.

Valid event values: deposit.received, deposit.confirmed, kyt_complete, ofac_complete, double_spend_alert, deposit.accepted, deposit.returned, deposit.frozen, transaction.pending, transaction.succeed, transaction.underpaid, transaction.overpaid, transaction.confirmed, transaction.timedout, transaction.cancelled, transaction.refund, transaction.settled. See Webhook events for each one.

How the test differs from a real event:

  • The URL and signing secret come from ByteFederal's configuration for the casino. You cannot send a test event to any other URL.
  • The payload is signed exactly like a real event.
  • The payload carries "test": true, and deposit_id and transaction_id are 0. No real deposit has id 0.
  • The request carries the header X-Webhook-Test: true.
  • Nothing is stored and nothing is retried. One call sends one request.
  • The request times out after 30 seconds, the same as real deliveries.
  • Redirects are not followed, the same as real deliveries.

The endpoint returns HTTP 200 whenever it made the delivery attempt, whatever your endpoint answered. Read delivered.

Response fields​

FieldTypeDescription
eventstringThe event that was sent.
urlstringWhere it was sent.
signedbooleanWhether the request carried X-Webhook-Signature.
signaturestring or nullThe X-Webhook-Signature value sent, or null if unsigned.
deliveredbooleantrue when your endpoint answered with a 2xx status.
status_codenumber or nullYour endpoint's HTTP status. null if no response arrived.
duration_msnumberHow long the attempt took.
response_excerptstring or nullThe first 500 characters of your endpoint's response body. null if no response arrived.
errorstring or nullWhy no response arrived (timeout, connection failure). null when a response arrived.
payloadobjectThe event payload that was sent.

Delivered​

Your endpoint answered 2xx:

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

The remaining examples leave out payload. It is always present.

Your endpoint answered with an error​

Any status outside 2xx, including a redirect, sets delivered: false:

{
"event": "deposit.accepted",
"url": "https://casino.example.com/webhooks/byteconnect",
"signed": true,
"signature": "704828d06759f1551858ece3c83e8cb4b036d9b0d8368576dc67b30e1b9d953c",
"delivered": false,
"status_code": 500,
"duration_ms": 97,
"response_excerpt": "upstream handler crashed",
"error": null
}

A 3xx status means your URL redirects. Real deliveries do not follow redirects either, so they fail the same way. Ask ByteFederal to configure the final URL.

No response: timeout or connection failure​

{
"event": "deposit.accepted",
"url": "https://casino.example.com/webhooks/byteconnect",
"signed": true,
"signature": "704828d06759f1551858ece3c83e8cb4b036d9b0d8368576dc67b30e1b9d953c",
"delivered": false,
"status_code": null,
"duration_ms": 30001,
"response_excerpt": null,
"error": "The operation timed out."
}

error describes the failure, for example The operation timed out. or a connection error. Do not match on its text.

Webhook URL is not a public address​

The test webhook only contacts public addresses. If the configured URL is an IP literal in a private, loopback or link-local range, or its hostname resolves to one, nothing is sent. The result has delivered: false, status_code: null, and an error saying the URL points to or resolves to a non-public address. Ask ByteFederal or BurraPay to set a public https:// URL.

No webhook configured​

If neither the casino nor any active API key that covers it has a webhook URL, nothing is sent:

{
"detail": "No webhook URL is configured for this entity"
}

The status is 409. Ask ByteFederal to set the webhook URL.

For every other error this endpoint returns, see Errors.

Rate limit​

The endpoint allows 10 calls per 60-second window per API key. The 11th call returns 429 with a Retry-After header. See Errors.

What your endpoint receives​

POST /webhooks/byteconnect HTTP/1.1
Content-Type: application/json
X-Webhook-Signature: 704828d06759f1551858ece3c83e8cb4b036d9b0d8368576dc67b30e1b9d953c
X-Webhook-Test: true

The body is the payload JSON. Use a test webhook to prove three things about your endpoint:

  1. It verifies the signature. Compute HMAC-SHA256 over the raw request body with the casino's webhook secret, hex-encode it, and compare with X-Webhook-Signature. See Webhooks.
  2. It ignores test events. An event with "test": true (or the X-Webhook-Test: true header) must not credit a player, change a balance or touch a real deposit. Answer 2xx and stop.
  3. It answers fast with 2xx. Real deliveries are retried when you answer anything else.
Verify against the raw body you received

The payload object in the test-webhook response is not byte-for-byte the body that was signed. The signed body has its keys in sorted order. Recompute the signature from the raw bytes your endpoint received, never from a re-serialized object.

Test mode​

ByteFederal can mark an API key or a casino as test mode. GET /casino/integration/key shows the key's mode. It does not show the casino's mode; ask ByteFederal to confirm it.

A deposit is recorded as test data when either the key that created it or its casino is in test mode.

What test mode changes:

  • The deposit is left out of bank settlement. The casino is not paid for it.
  • ByteFederal's internal notices about the deposit are marked as test.

What test mode does not change:

  • The address is a real mainnet address, and the crypto sent to it is real.
  • Player KYC runs for real. The player gets a real SMS.
  • OFAC and KYT screening run for real.
  • Webhooks are sent as normal. Their payloads do not say the deposit is test data, and they do not carry "test": true.
  • The player gets a real receipt after accept.
  • A return sends real crypto to the address you give.
Test mode is not a sandbox

Test mode only changes accounting. Funds sent to a test-mode deposit are real, and funds returned from one are gone from ByteFederal's wallets.

Mainnet walkthrough​

This walkthrough takes one player through KYC, one deposit through accept, and a second deposit through return. It uses real crypto.

You need:

  • An admin API key for the casino.
  • A phone you control, to receive the KYC link.
  • A wallet with a small amount of BTC, LTC or ETH.
  • A second wallet address you control on the same chain, to receive the return.
  • Your webhook endpoint running, and a way to see what it receives.

1. Check the key and the webhook​

Run the key check. Confirm the casino is enabled and the webhook points at your endpoint. Then send a test webhook and confirm delivered: true.

2. Register a new player​

Pick a gambler_ref you have never used, for example sample-player-001. Create a deposit with it and your phone number:

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",
"amount": 5
}'

A new player gets kyc_required, and an SMS with a verification link goes to the phone:

{
"status": "kyc_required",
"message": "Identity verification required. A verification link has been sent."
}

If the phone already belongs to a verified identity, the message is We found an existing account. A confirmation link has been sent. instead.

No deposit is created yet. Open the link on the phone and complete it. See Player KYC.

3. Create the first deposit​

Send the same request again. Until verification completes you get kyc_pending:

{
"status": "kyc_pending",
"message": "Identity verification is pending. Please complete verification to proceed."
}

Once it completes, you get status: "ok" with a deposit. Note deposit_id, address, crypto_amount and expires_at. See Creating deposits for every field.

4. Fund it​

Send exactly crypto_amount to address. Players are shown a 15-minute window; a payment is honored until expires_at, 30 minutes after creation. See Expiry and late payments.

If you send a different amount, the deposit can still be accepted, but accept then needs "adjust_to_received": true. See Accept, return, freeze.

5. Watch the webhooks​

As the payment is seen, confirmed and screened, your endpoint receives events including deposit.received, ofac_complete, deposit.confirmed and kyt_complete, along with transaction.* status events. See Webhook events for what each one carries.

Do not depend on the order they arrive in. Use the acceptable field instead: it is on every deposit webhook and on GET /casino/deposit/{id}, and it turns true when accept would succeed.

curl https://quinix.byteconnect.us/casino/deposit/$DEPOSIT_ID \
-H "X-API-Key: $API_KEY"

6. Accept​

When acceptable is true:

curl -X POST https://quinix.byteconnect.us/casino/deposit/$DEPOSIT_ID/accept \
-H "X-API-Key: $API_KEY"

Check that:

  • The response has "decision": "accepted".
  • Your endpoint receives deposit.accepted.
  • The player's phone (and email, if you sent one) receives a receipt.

7. Create and fund a second deposit​

Create another deposit with the same gambler_ref. The player is verified now, so you get status: "ok" straight away. Fund it as in step 4.

8. Return it​

Wait until the deposit is confirmed and its KYT result has passed: deposit.confirmed and a passed kyt_complete have arrived, or GET /casino/deposit/{id} shows status: "Confirmed" and kyt_status: "passed". Then return it to your second wallet:

curl -X POST https://quinix.byteconnect.us/casino/deposit/$DEPOSIT_ID/return \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"return_address": "<your second wallet address>",
"reason": "Integration test"
}'
Check the return address

The API does not validate return_address. It accepts any non-empty string. A wrong address, or an address on another chain, loses the funds. Copy it from your wallet and check it before sending.

Check that:

  • The response has "decision": "returned" and a return_id.
  • Your endpoint receives deposit.returned.
  • The crypto arrives in your second wallet.

Each deposit can be decided once. A second return call gets 400 Decision is already 'returned', cannot return.