The Pix2Depix REST API converts BRL (Brazil Pix) to and from DePix, a BRL-pegged asset on the Liquid Network — so you can accept Pix payments that settle on-chain and pay out on-chain balances back to a Pix key.This guide walks you through a deposit (BRL → DePix) from first request to confirmation, then shows an optional payout (DePix → BRL). More about DePix at depix.info.
Every request is authenticated with a Bearer JWT (RS256), and you issue it yourself from the #Bot section of your private Telegram channel with Eulen. There are two ways to get one:
Client credentials (recommended)./addclientcredentials <label> gives you a client_id and client_secret. Exchange them at POST /api/v2/auth/login for a short-lived access token plus a refresh token, and renew with POST /api/v2/auth/refresh.
Legacy API token./apitoken <label> <days> [all|deposit|withdraw|user] returns a long-lived token directly, valid for up to 365 days.
Either way the header is the same. Send it on every call:
GET /ping validates your token and echoes back its decoded claims, so it's the fastest way to confirm your credentials and scopes are correct:
Your token carries a scope claim, an array holding any of deposit, withdraw and user. Calling an endpoint outside your granted scopes returns 403 Forbidden. Client credentials spell the payout scope withdrawal; both spellings are accepted on the API. See the Authentication page for the full claim reference.
Hold on to id — you'll use it to track the deposit in step 4.
There is no idempotency — do not retry blindly
This API has no idempotency key. X-Nonce is generated by the server and returned in the response header for tracing; a nonce you send is not read. If a deposit or withdrawal times out, check its status before resending, or you may create it twice. See Synchronous requests & safe retries.
The response gives you everything you need to present the payment:
qrCopyPaste — the Pix "copia e cola" payload. This is the one that gets paid: it is always present, and it works on its own. Offer it as a copy-paste code, and render your own QR image from it if you want one you fully control.
qrImageUrl — a PNG of the same QR, hosted by us, for when you would rather not render one. It can come back as an empty string, and that is not an error: we only hand you a URL once we know it will serve. Check it before you use it, and fall back to qrCopyPaste.
One QR, one payment, one window
Instruct the end user to pay only with the qrImageUrl or qrCopyPaste returned for this deposit. A payment made any other way does not reach it — not the bank app's "repeat transfer" option, not a direct transfer to the destination account, not standalone banking details, and not an in-app AI assistant asked to create or edit the payment.Each QR is single-use and tied to one deposit id. Paying it twice, or reusing it for a different purchase, will not credit a second time. Pix QRs also expire: once the window closes, create a new deposit for a fresh QR rather than retrying the old one.
Once the user pays, the deposit moves through a series of statuses. Prefer webhooks — Eulen sends an HTTP POST callback to your registered endpoint as the status changes, so you don't have to poll.Treat approved as your confirmation signal: it means the payment was received and cleared, and the DePix will be sent shortly. It fires faster than depix_sent, so it's the recommended trigger for fulfilling the user's order.As a fallback — for example, if a webhook delivery is missed — poll GET /deposit-status:
Common deposit statuses you'll observe:
Status
Meaning
pending
QR generated, awaiting payment
under_review
Paid, under review by us
approved
Received & cleared — DePix will be sent soon (confirm on this)
depix_sent
DePix sent
delayed
Held until delayUntil
expired
QR expired before payment
refunded
Refunded to payer (e.g. via MED)
canceled
Canceled
error
Contact support
Held states
A deposit may pause in under_review or delayed before reaching approved. These are expected intermediate states — wait for approved rather than treating a held deposit as failed. A new end user's first deposit is the most common reason for the extra check, and it usually proceeds once cleared.
To reconcile a batch of deposits (e.g. after downtime), use GET /deposits?start=&end=&status= as the documented webhook fallback. start is inclusive and end is exclusive (start <= x < end); dates are YYYY-MM-DD or RFC3339.
If your token has the withdraw scope, you can send DePix back out as a Pix payout with POST /withdraw. Provide the destination pixKey, exactly one of depositAmountInCents (DePix to send) or payoutAmountInCents (BRL to receive), and a beneficiary identification — at least one of taxNumber or euid.
The pixKey must belong to the beneficiary you identify with taxNumber / euid. If you send both, they must match — the request is rejected outright when they disagree, and a mismatch the API lets through can still be rejected by the receiving bank.
Track the payout with GET /withdraw-status?id=<withdrawalId>, or via the withdraw webhook.
Authentication — full JWT claim reference, scopes, and how to validate tokens.
Webhooks — register an endpoint and handle the deposit, withdraw, and med event types.
Errors — HTTP status codes and the response.errorMessage envelope.
Troubleshooting — the mistakes integrations actually make, listed by the symptom you see.
Changelog — track API changes, including the beneficiary-identification requirement (effective 2026-05-01).
MED webhooks
The med event type notifies you when a MED (Pix special refund) is filed against a past deposit. Register it the same way as the other two, with /registerwebhook med <url> <secret>.