1. Docs
Pix2DePix API
  • ⚡ Quickstart
  • 📝 Changelog
  • 📖 Glossary
  • Docs
    • 🔑 Authentication
    • ⚠️ Errors & the response envelope
    • 🧩 Troubleshooting
    • ✅ Possible Statuses
      • 📥💰 Deposit Statuses
      • 📤💸 Withdraw Statuses
    • 🧩 Advanced
      • 🔀 Synchronous requests & safe retries
    • 🛡️ Security & Limits
      • 🪲 Bug Bounty
      • 🚦 API Limits
      • 🧱 Firewall
      • ✅ Best Practices
    • 🚀 Features
      • ⏱️ QR Delay
  • API Endpoints
    • Ping
      GET
    • Deposit (PIX ➔ DePix)
      POST
    • Deposit Status
      GET
    • Deposits
      GET
    • User Info
      GET
    • Withdraw
      POST
    • Withdraw Status
      GET
  • Webhooks
    • 🪝 Webhooks
    • Deposit Webhook
    • Withdraw Webhook
    • MED Webhook
  • Schemas
    • AllPossibleObjResponses
    • StandardResponse
    • PingObjOrError
    • JWTClaims
    • ObjResponse
    • ErrorObj
    • PingObj
    • ErrorResponse
    • DepositRequest
    • DepositObjOrError
    • DepositObj
    • PingResponse
    • DepositResponse
    • DepositStatusObj
    • DepositStatusResponse
    • DepositWebhookBody
    • DepositsResponse
    • DepositStatus
    • UserInfoResponse
    • WithdrawStatusResponse
    • WithdrawStatusObj
    • WithdrawResponse
    • WithdrawObj
    • WithdrawStatus
    • WithdrawWebhookBody
    • MEDWebhookBody
    • RejectionReasons
  1. Docs

🧩 Troubleshooting

This page is organised by what you see, not by what we call it. Each entry names the symptom, the cause behind it, and the fix. If you are integrating for the first time, reading it once will save you the two or three hours everyone else spent finding these.
Check the status page before you debug your own code
Open status.eulen.app first. A maintenance freeze or an incident on our side produces symptoms that look exactly like a bug in your integration — most often a 503.
There is no sandbox yet
Every call goes to production and moves real money. A dedicated test environment is planned and on our roadmap. Until it ships, validate your credentials and scopes with GET /ping, which creates nothing, and run your first end-to-end tests with the smallest amounts you can.

Every request returns 404#

Almost always the URL, not the endpoint. Two causes produce the identical response:
What you sentResult
https://depix.eulen.app/deposit404 — the /api prefix is missing
https://depix.eulen.app/api//deposit404 — your base URL ended in a slash, producing //
https://depix.eulen.app/api/depositcorrect
The double slash is the one that hides, because most HTTP clients let you set a base URL and it looks right in your config. // is not normalised here — it is a different path, and it 404s.

Invalid scope. when you create a credential#

The two credential methods spell the payout scope differently, and each command accepts only its own spelling:
CommandPayout scope
/addclientcredentialswithdrawal
/apitoken (legacy)withdraw
Copying the scope across from an existing legacy token is the usual way to hit this. See Authentication.

403 Forbidden on a call you expected to work#

Your token is valid, but it does not carry the scope this endpoint requires. Call GET /ping and compare the scope array it echoes back against what the endpoint needs — deposit, withdraw / withdrawal, or user.
Note that /user-info needs the user scope, which is easy to leave out when you created a credential scoped only to payments.

401 Unauthorized on a call that worked before#

Three possibilities, in order of likelihood:
1.
Your access token expired. Client credentials issue a short-lived access token; renew it with POST /api/v2/auth/refresh rather than logging in again on every call.
2.
The token was revoked. Issue a new one — both methods are self-service.
3.
The header is malformed. It is Authorization: Bearer <token>.
GET /ping tells you which it is: if it also returns 401, the problem is the token itself, not the endpoint you were calling.

Your error handler crashes instead of reporting the error#

You are parsing response.errorMessage, and the response that arrived has errorMessage at the top level with no response wrapper. 401, 403 and 429 answer that way.
Read errorMessage from the top level and from inside response, whichever is present. See Errors & the response envelope.

A deposit or payout was created twice#

Your HTTP client retried on its own. This API has no idempotency key, so a retry creates a second operation.
The trap is 520: it is a business rejection, but it sits in the 5xx range, and most HTTP libraries retry 5xx automatically. A timeout surfacing as 503 is the other path in.
Turn off automatic retry on POST /deposit and POST /withdraw. When one of them times out, confirm the outcome with GET /deposit-status or GET /withdraw-status before resending. See Synchronous requests & safe retries.

A deposit is refused and the message names a minimum in hours#

Your account has a minimum QR delay configured, which makes delayDepixInHours required on every deposit — including the ones you never meant to delay. Omitting it is refused, and so is a value below the minimum.
The accepted range is 1 to 720 hours. See QR Delay.

A deposit or payout is refused with a reference number#

That is a 422: a compliance decision about that payer, and it is definitive. Retrying will not change it, and because there is no idempotency a retry can create a second operation.
Log the reference number in the message and quote it to support — without it the case cannot be looked up. See Errors & the response envelope.

A payout is refused#

The two common causes:
The pixKey does not belong to the beneficiary you identified with taxNumber / euid. If you send both and they disagree, the request is rejected outright — and a mismatch we let through can still be refused by the receiving bank.
The amount is outside the accepted range. The error message states the range. If you are hitting a daily ceiling rather than a per-operation one, GET /user-info shows your current daily volume and when it resets.

The webhook never arrived#

Webhook delivery is single-attempt. There is no retry, so anything that goes wrong on one delivery is permanent for that event.
Check, in this order:
1.
Did your endpoint answer 200 or 201? Anything else counts as a failed delivery — including a 3xx redirect.
2.
Did it answer within 15 seconds? Acknowledge first, process afterwards.
3.
Is your handler rejecting our auth? We send Authorization: Basic followed by the secret you registered, as-is.
4.
Is the URL still the one you think? Changing a webhook URL is two steps — delete the old registration, then register the new one. Registering again over the top does not replace it.
Then recover the events you missed: sweep GET /deposits?start=&end=&status= (start inclusive, end exclusive). Only deposits have a batch sweep — for payouts, poll GET /withdraw-status with the IDs you hold.
Reconciliation is part of a correct integration
Because there is no retry, a periodic sweep is not a safety net you add later — it is the only way to recover a missed event. Treat your reconciliation job and your webhook handler as two paths into the same idempotent state machine. See Webhooks.

Still stuck#

Quote these three things and support can find the call immediately: the X-Request-ID and X-Nonce from the response headers, and the deposit or withdrawal id. If it was a 422, the reference number from the message matters more than all three.
Modified at 2026-08-12 17:08:35
Previous
⚠️ Errors & the response envelope
Next
📥💰 Deposit Statuses
Built with