Getting Started



Base URL

All endpoints live under:

https://dominipay.com/api

Sandbox and live use the same host. The credentials you send decide the environment.

Credentials

Every request is authenticated with a token and a secret. You find both in your dashboard.

Endpoint typeWhere to send token and secret
POST endpointsIn the JSON body. The body fields are required by every POST endpoint.
GET /transactions/payment/{idTransaction}, GET /transactions/pixout/{idTransaction}, GET /account/balanceIn the token and secret HTTP headers. Body or query values are ignored.
GET /wallet/card/refund/{refundId}In the token and secret HTTP headers.

The authentication layer of the POST endpoints also reads the token and secret headers, but each POST endpoint then validates the body and answers 422 when the fields are missing there. Always put them in the body for POST requests.

POST example:

curl -X POST https://dominipay.com/api/wallet/deposit/payment \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "token": "YOUR_TOKEN",
    "secret": "YOUR_SECRET",
    "amount": 10.00,
    "method_pay": "pix",
    "debtor_name": "John Doe",
    "email": "[email protected]",
    "debtor_document_number": "12345678909",
    "phone": "11900000000",
    "postback": "https://example.com/callbacks/pix-in"
  }'

GET example:

curl https://dominipay.com/api/account/balance \
  -H "Accept: application/json" \
  -H "token: YOUR_TOKEN" \
  -H "secret: YOUR_SECRET"

Never put credentials in a URL or query string, and never expose them in a browser or mobile app. Call the API from your server.

Authentication errors

HTTPBodyMeaning
400{"error": "Token ou Secret ausentes", "message": "..."}token or secret missing.
401{"status": "error", "message": "Token ou Secret inválidos"}Wrong pair.
401{"status": "error", "message": "Usuário sem permissões. Fale com seu gerente."}Account blocked or not approved.
403{"status": "error", "error_code": "REFUND_ONLY", ...}Account limited to refunds. Only POST /wallet/card/refund and GET /wallet/card/refund/{refundId} work.

Some messages are in Portuguese. Branch on the HTTP status and on error_code, not on message.

Environments: sandbox and live

Each account has two credential pairs:

  • Live: your production token and secret.
  • Sandbox: token starting with tk_test_ and secret starting with sk_test_.

Sandbox only covers card payments. Anything that moves real BRL or crypto rejects sandbox credentials with HTTP 403.

EndpointSandboxLive
POST /wallet/deposit/payment with method_pay=cardYesYes
POST /wallet/deposit/payment with method_pay=pixNo (403)Yes
POST /wallet/card/charge, POST /wallet/card/confirmYesYes
POST /wallet/card/refund, GET /wallet/card/refund/{refundId}Yes (sandbox charges only)Yes (live charges only)
GET /transactions/payment/{idTransaction}, GET /transactions/pixout/{idTransaction}YesYes
GET /account/balanceYes (USD block shows the sandbox balance, mode: test)Yes
POST /pixoutNo (403)Yes
POST /crypto/withdraw, POST /crypto/withdraw/statusNo (403)Yes

In sandbox, use card processor test cards such as 4242 4242 4242 4242 with any future expiry date and any CVC. No real money moves.

Amounts and currencies

  • PIX amounts are in BRL, as decimal numbers (10.50).
  • Card amounts are in USD, as decimal numbers (100.00). The minimum card charge is USD 5.00.
  • Responses return amounts as numbers, except the crypto endpoints, which return decimal strings ("50.00").

Idempotency

Only two endpoints accept an idempotency key:

EndpointBehavior
POST /wallet/card/chargeSend Idempotency-Key (header) or idempotency_key (body). A retry with the same key returns the same charge. Without a key, every request is a new charge.
POST /wallet/card/refundSame header or body field. Without a key, one is derived from the transaction and the amount, so an identical retry is collapsed into one refund.

Use one key per logical operation (for example your order id plus the attempt number). The card processor keeps keys for 24 hours.

The other POST endpoints (/wallet/deposit/payment, /pixout, /crypto/withdraw) have no idempotency key. If one of them times out, check the transaction status or your balance before sending the request again.

Rate limits

EndpointLimitResponse
POST /pixout1 request per minute per source IP429 {"status": "error", "message": "Muitas requisições. Tente novamente mais tarde."}
POST /pixout1 withdrawal attempt per account every 60 seconds429 with error_code: RATE_LIMITED
POST /wallet/card/charge, POST /wallet/card/confirmPlatform wide limit shared by all merchants429 with error_code: RATE_LIMITED

The other endpoints have no fixed limit, but do not poll in tight loops. Cache the balance for a few seconds and prefer callbacks over polling for status.

On a 429, wait at least 60 seconds before retrying POST /pixout, and use exponential backoff elsewhere.

Response format

All responses are JSON. Send Accept: application/json so that framework level errors also come back as JSON.

Errors usually look like this:

{
  "status": "error",
  "message": "Transaction not found.",
  "error_code": "TRANSACTION_NOT_FOUND"
}

See Error codes for the full list.

Next steps


Did this page help you?