Quickstart
Complete a full PIX deposit in the staging environment — from credentials to a credited
balance — in about 15 minutes. You need curl, a publicly reachable HTTPS endpoint for
webhooks, and staging credentials.
Nothing here moves real money.
The whole flow
Steps 1–3 and 6 are calls you make. Step 5 is the one you receive — and it is the step most integrations get wrong, because it arrives asynchronously and can arrive more than once.
Step 1 — Get an access token
curl --request POST \
--url 'https://api.sdb.lbpay.com.br/v1/oauth2/token' \
--header 'accept: application/json' \
--header 'content-type: multipart/form-data' \
--form client_id=YOUR_CLIENT_ID \
--form grant_type=client_credentials \
--form client_secret=YOUR_CLIENT_SECRET
Export the token so the following steps can reuse it:
export TOKEN="the_access_token_you_received"
export API="https://api.sdb.lbpay.com.br/v1"
The token is valid for 2 hours. See Authentication for automatic renewal.
Step 2 — Register your webhook
Deposits are confirmed asynchronously. Register the endpoint that will receive events before you create a charge, or you will have no way of learning that the payment arrived.
LB Pay probes the URL during registration. If it is unreachable, still returning 404,
or not yet serving HTTPS, this call fails with webhook_unreachable or webhook_timeout —
not later, but right here.
curl --request PUT \
--url "$API/webhook" \
--header "Authorization: Bearer $TOKEN" \
--header 'content-type: application/json' \
--data '{
"url": "https://your-platform.example.com/webhooks/lbpay",
"type": 0,
"authenticationType": 1,
"authentication": { "type": "bearer", "token": "YOUR_WEBHOOK_TOKEN" },
"events": ["pixChargePaid", "pixChargeExpired"]
}'
type selects the domain this configuration covers — 0 Pix In, 1 Pix Out, 2 Pix
Refund. The token is yours: LB Pay sends it back on every notification so you can reject
anything that does not carry it.
Your endpoint must respond 2xx within 5 seconds. Persist the event and return
immediately; do the business logic afterwards, off the request path — see
Webhooks.
Step 3 — Create a deposit charge
curl --request POST \
--url "$API/pix/deposit/immediate-charge" \
--header "Authorization: Bearer $TOKEN" \
--header 'content-type: application/json' \
--data '{
"externalId": "3f2b1c4e-9a7d-4e21-b8f0-5c6d7e8a9b01",
"amount": 5000,
"expiresIn": 600,
"pixKey": "YOUR_OPERATOR_PIX_KEY",
"expectedPayer": { "taxId": "12345678909" }
}'
5000 is R$ 50,00. Sending 50.00 is not a smaller amount — it is a different request
altogether. This applies to every endpoint that moves money.
| Field | Why it matters |
|---|---|
externalId | Your own identifier, unique per operation, up to 100 characters. It is the idempotency key — persist it before sending. See Idempotency. |
expiresIn | Lifetime of the QR Code in seconds. Use at least 600, and make sure the countdown you show the player matches it exactly. |
pixKey | The destination key — yours, not the player's. This is the account being credited. |
expectedPayer.taxId | The player's CPF. Ownership rules compare it against the CPF that actually pays — see Ownership rules. |
The response returns 201 with a chargeId, the copy-and-paste payload in brCode, and
status PENDING.
Step 4 — Simulate the payment
In staging you do not need a bank app. Simulate the player paying:
curl --request POST \
--url "$API/pix/mock/simulate-payment" \
--header "Authorization: Bearer $TOKEN" \
--header 'content-type: application/json' \
--data '{
"chargeId": "THE_CHARGE_ID_FROM_STEP_3",
"receiverCnpj": "YOUR_RECEIVING_CNPJ"
}'
chargeId and receiverCnpj are both required. Everything else — amount, payer details —
is recovered from the charge you created in step 3.
mock/simulate-payment does not exist in production. It is the supported way to exercise
the credit path during development and homologation.
Step 5 — Receive pixChargePaid
Your endpoint receives a POST describing the event. This is the signal — and the only
signal — that authorises crediting the player's wallet.
{
"event": "pixChargePaid",
"status": "paid",
"chargeId": "...",
"externalId": "3f2b1c4e-9a7d-4e21-b8f0-5c6d7e8a9b01",
"endToEndId": "E12345678202608181200abcdef12345",
"amount": 5000
}
The platform retries webhook delivery, so the same event can arrive more than once. Before
crediting, check whether you have already processed this endToEndId. Skipping this check
credits the player twice for one deposit.
Store the endToEndId — it is the identifier that ties this transaction to statements,
refunds and support tickets.
If the event never arrives, do not assume failure. Query the charge directly:
curl --request GET \
--url "$API/pix/deposit/immediate-charge/THE_CHARGE_ID" \
--header "Authorization: Bearer $TOKEN"
Webhooks are the primary channel; polling is the mandatory fallback. See Polling.
Step 6 — Confirm the balance
curl --request GET \
--url "$API/balance/realtime" \
--header "Authorization: Bearer $TOKEN"
The deposited amount is now reflected in your LB Pay balance.
What to build next
You have the happy path. Production readiness is mostly about the unhappy ones:
| Next | Why |
|---|---|
| Idempotency | Prevents duplicate payments after a network error |
| Retries and timeouts | A timeout is not a failure |
| Withdrawals | The most critical flow for iGaming |
| Go Live checklist | The formal acceptance criteria for production access |