# API v2 Integrate Pix, balance, statement, charges and notices into your system with one token and a few calls. Base URL: https://bank.granseuk.com/api/v2 ## Overview Base URL: https://bank.granseuk.com/api/v2 Active at this bank: - Send Pix to a key - Receive Pix by charge (dynamic QR with txid) - Receive Pix straight into the account keys - Balance, statement and PDF receipt - Transfer between accounts of the bank API v2 brings together what you need to integrate Pix, balance, statement, charges and notices into your system, shaped like the most widely used Pix APIs: one token, short paths and predictable responses. If you already integrate with another Pix provider, you usually just change the base URL and credentials. The money rules are the same as the v1 API: balance, fees, limits, idempotency, client certificate (mTLS) and any function your bank turned off. - Amounts in BRL, as a number (25.5) in payments, balance and statement; as a string ("49.90") in charges, like the BACEN standard. - Dates in ISO 8601 (UTC). - Payment states: PROCESSING, LIQUIDATED, CANCELED, REFUNDED, WAITING_APPROVAL. - Charge states: ATIVA, CONCLUIDA, REMOVIDA_PELO_USUARIO_RECEBEDOR, REMOVIDA_PELO_PSP. - The v1 API (at /docs) is unchanged and works alongside. ## Start in 3 steps - In the bank panel, open API, tap New key, choose Production and use the "Full integration (receive and send Pix)" shortcut (it ticks balance, statement, lookups, charge by Pix, send Pix and transfer). On creation the panel shows the Client ID, the Client Secret (the key, shown once: store it) and the base URL. - Exchange the credentials for a token: POST /oauth/token (clientId = first 14 characters of the key, clientSecret = the key). - Call the routes with Authorization: Bearer . On every payment, send x-idempotency-key. ## Authentication and permissions Use the 1-hour token from /oauth/token as Authorization: Bearer. Ask for a new one shortly before expiry or on a 401. The raw sk_ key as Bearer also works. The key defines what the token can do: the scope field of the request is ignored. | Scope | Your key permission | Routes | | --- | --- | --- | | account.read | balance:read | GET /accounts/balances | | transactions.read | transactions:read | GET /accounts/transactions | | pix.read / cob.read | pix:read | GET /accounts/keys, GET /pix/payments/*, GET /cob/{txid} | | pix.write | pix:send | POST /pix/payments/dict | | cob.write | pix:write | PUT /cob/{txid}, POST /cob | | internal-transfer.write | transfers:write | POST /internal-transfers | | internal-transfer.read | transactions:read | GET /internal-transfers/{endToEndId}, GET /internal-transfers/idempotencyKey/{key} | Client certificate (mTLS): optional by default. If your bank turned the requirement on for your account, calls must present it (403 certificate_required otherwise). ## Other functions on your account Besides the routes on this page, your bank enabled these functions in the v1 API. The same token (Authorization: Bearer) works on them; the full reference for each is in the v1 documentation. | Function | Routes | Key permission | | --- | --- | --- | | Transfer between accounts (also in v2: /internal-transfers) | POST /v1/transfers | transfers:write | | Payment links | POST /v1/payment-links, GET /v1/payment-links | pix:write | | Split of incoming payments | GET/PUT /v1/split, GET /v1/split/lookup, GET /v1/split/history | split:read, split:write | | Split to a Pix key | PUT /v1/split/pix | split:write | | Payroll | /v1/payroll/* | payroll:read, payroll:write | Full reference: /docs (v1 API). ## Send a Pix: from request to confirmation - Create a unique x-idempotency-key for the request (for example, your own order id) and keep it. - POST /pix/payments/dict with the Pix key, the amount and the x-idempotency-key. The response is 202 with status PROCESSING: the amount has already left the balance. - Wait for the outcome. With webhooks on, it arrives in the transfer notice (status LIQUIDATED) or cashout notice (status CANCELED). Without webhooks, call GET /pix/payments/idempotencyKey/{key} every few seconds until the status is no longer PROCESSING. - LIQUIDATED: done. The endToEndId is filled in and the receipt is at GET /pix/payments/receipt/{endToEndId}. - CANCELED: the Pix did not go out and the amount returns to the balance by itself. You may try again with a NEW key. - If the connection drops or times out, do NOT create another key: repeat the POST with the SAME x-idempotency-key (it returns the same payment, never paying twice) or look it up by key. | status | Meaning | | --- | --- | | PROCESSING | Accepted, on its way to the destination bank. Not final yet. | | LIQUIDATED | Done: the money arrived. | | CANCELED | It did not go out; the amount returned to the balance. | ## Receive a Pix: from charge to confirmation - PUT /cob/{txid} (or POST /cob) with the amount and validity. The response carries the pixCopiaECola: show it (or its QR code) to the payer. - When the payer pays, the money lands in the balance right away and the charge becomes CONCLUIDA. With webhooks on, the receive notice arrives; without webhooks, call GET /cob/{txid} until the status is CONCLUIDA (the pix list carries the endToEndId). - Release the order only when the charge is CONCLUIDA. ATIVA means waiting for payment; REMOVIDA_PELO_PSP is an expired charge. - A Pix paid straight into an account key (GET /accounts/keys) has no charge: it shows up as CREDIT in GET /accounts/transactions and in the receive notice. - To check the money, use GET /accounts/balances (available) and GET /accounts/transactions (statement). ## Sandbox (test environment) Test the whole integration without moving real money. In the panel, under API, tap New key and choose Sandbox: the key is born with the sk_sbx_ prefix and a fake account holding R$ 10,000.00. Everything else matches production: the same base URL, the same token (POST /oauth/token with the sandbox key's Client ID and Client Secret), the same routes, the same fields and the same errors. Only the money is fake. - Sent Pix (POST /pix/payments/dict and /qrc): answers 202 already with the endToEndId and completes by itself in about 4 seconds (LIQUIDATED), with the transfer notice. The test fee is R$ 1.00. - Key falha@sandbox.test (EMAIL): the Pix is accepted and fails after about 4 seconds; the amount returns and the cashout notice arrives (CANCELED). - Key recusa@sandbox.test (EMAIL): refused immediately (400), nothing is debited. - Pix charge (PUT /cob/{txid}): stays ATIVA until you pay it with the sandbox command below; then it becomes CONCLUIDA, the balance goes up and the receive notice arrives. The pixCopiaECola of a sandbox charge can also be paid through POST /pix/payments/qrc. - Transfer between accounts (POST /internal-transfers): use document 111.444.777-35 (any name) as the test destination account. - Key lookup (GET /pix/keys/{key}) returns test data; naoexiste@sandbox.test answers 404. - Webhooks (POST /webhooks/{type}): apply only to the sandbox key and receive only test notices; they do not need to be enabled for the account. Commands that play the part of the outside world (sandbox keys only; with a production key they answer 403): | Command | What it does | | --- | --- | | POST /sandbox/cob/{txid}/pay | Pays the charge: balance goes up, status CONCLUIDA, receive notice. | | POST /sandbox/pix/receive | Simulates a Pix paid straight to your key. Body: { "amount": 25.50, "payer": "Someone" }. | | POST /sandbox/pix/payments/{endToEndId}/complete | Speeds up the completion of a sent Pix (transfer notice). | | POST /sandbox/pix/payments/{endToEndId}/fail | Forces a sent Pix to fail: the amount returns (cashout notice). | | POST /sandbox/balance/topup | Adds fake balance. Body: { "amount": 500 }. | | GET /sandbox/info | Lists these test keys and commands. | The sandbox is isolated: it does not use the real balance, does not go through the provider, and the endToEndIds it generates start with E99999999 (a bank that does not exist), so they are never mistaken for a real Pix. Test data is erased after 30 days. When everything works, create a production key and swap the Client ID and Client Secret: the code does not change. ## Idempotency Every payment requires the x-idempotency-key header (1 to 50 letters and digits). Repeating the same key returns the SAME payment, never paying twice. If the connection drops and you do not know whether the request arrived, repeat it with the same key or call GET /pix/payments/idempotencyKey/{key}. ## Errors { "type": "onz-0008", "title": "Invalid request", "status": 400, "detail": "Saldo insuficiente", "instance": "/api/v2/pix/payments/dict", "statusCode": 400, "error": "insufficient_funds", "message": "Saldo insuficiente" } | type | title | When | | --- | --- | --- | | onz-0001 | Invalid credentials | Invalid clientId or clientSecret (401) | | onz-0002 | Invalid params | Missing or invalid field; the message says which (400) | | onz-0003 | Invalid token | Missing, invalid or expired token, or revoked key (401) | | onz-0004 | Internal server error | Our failure; keep the ref (500) | | onz-0005 | Server shutting down | System busy: retry shortly (503) | | onz-0006 | Invalid token role | The key lacks the route's permission, the bank turned the function off or the mTLS certificate is missing (403) | | onz-0007 | Invalid pix entry | Invalid Pix key (400) | | onz-0008 | Invalid request | A business rule refused it (balance, limit, recipient…), call limit or a route the bank does not have. Nothing was debited (400, 429, 501) | | onz-0009 | Pix not found | Payment, charge or transfer not found in this account (404) | | onz-0010 | Invalid QR code | Invalid QR code, or an amount different from the one sent (400) | | onz-0011 | Invalid idempotency key | The x-idempotency-key is missing or invalid (400) | | onz-0012 | Webhook not found | Webhook not found (404) | The error body carries type (the onz-XXXX code from the table), title, status, detail and instance, as well as statusCode, error (the detailed code, such as insufficient_funds) and message. Decide by the HTTP status and the type; the error field gives the exact reason. On a 5xx error a ref also comes back: keep it when contacting support. ## Migrating from another provider - Change the base URL to https://bank.granseuk.com/api/v2. - Replace clientId and clientSecret with those of your key (see Authentication). - POST /pix/payments/dict answers 202 with { endToEndId, eventDate, id, payment, type }. endToEndId may be null until the Pix moves on; look it up by idempotency key. - GET /pix/payments/{endToEndId} returns { data: {...} }. It also accepts the transactionId. - The id field is a stable number, but it cannot be used for lookups: use endToEndId or transactionId. - The error codes (type onz-XXXX) and the scope names the token returns (pix.write, cob.write, account.read…) are the same; when creating the key in the panel, permissions have their own names (pix:send, pix:write…): see the permissions table. ## Not available yet - Creating Pix keys by API (keys are created in the panel) and refunding a received Pix. - Bank slips (/billets) and TED in this format. - Charges with due date (/cobv), recurring (/cobr) and Pix Automático. - Sandbox keys (sk_sbx_) cannot exchange a token; use v1 to test without real money. Routes of this standard that do not exist yet answer 501 not_supported, with an explanation (for example, POST /accounts/keys). ## Integrating with AI This whole documentation, as plain text, is at /docs/v2/llms.txt (add ?lang=en for English). Paste it into your assistant and ask for the code. ## API reference ### Authentication #### POST /oauth/token — Get an access token Exchanges clientId and clientSecret for an access token (OAuth 2.0 client credentials). The token is valid for 1 hour; send it as Authorization: Bearer on every other route. Accepts JSON, a form body (client_id, client_secret, grant_type) or Authorization: Basic base64(clientId:clientSecret). **Request body** - `clientId` (string, required): The first 14 characters of your API key (e.g. sk_live_AbCdEf) or the key id. - `clientSecret` (string, required): The full API key (sk_live_…). - `grantType` (string, required): Always client_credentials. - `scope` (string): Ignored: the token carries all of the key's permissions. **Code sample (curl)** curl -X POST 'https://bank.granseuk.com/api/v2/oauth/token' \ -H 'Content-Type: application/json' \ -d '{"clientId":"sk_live_AbCdEf","clientSecret":"sk_live_AbCdEf…chave-completa","grantType":"client_credentials"}' **201** — Token issued { "tokenType": "Bearer", "expiresAt": 1792529169, "refreshExpiresIn": 0, "notBeforePolicy": 0, "accessToken": "v2t_Zk3q…", "scope": "account.read transactions.read pix.read cob.read cob.write pix.write" } **401** — Invalid clientId/clientSecret, or revoked/expired key { "type": "onz-0001", "title": "Invalid credentials", "status": 401, "detail": "clientId ou clientSecret invalidos, ou chave revogada/expirada", "instance": "/api/v2/oauth/token", "statusCode": 401, "error": "invalid_client", "message": "clientId ou clientSecret invalidos, ou chave revogada/expirada" } - expiresAt is the expiry instant in Unix seconds. - The token stops working the moment its key is revoked. ### Account #### GET /accounts/balances — Get the account balance Balance in BRL. available is what can be spent now; blocked is what is on hold (by a bank review, for example). Permission: account.read → balance:read **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/accounts/balances' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "data": [ { "eventDate": "2026-10-20T14:00:00.000Z", "balanceAmount": { "currency": "BRL", "available": 1234.56, "blocked": 0, "overdraft": 0 } } ] } #### GET /accounts/transactions — List account transactions The account statement, newest first. Dates are inclusive (Sao Paulo time zone). Permission: transactions.read → transactions:read **Query parameters** - `event_date_start` (date-time): Start date (ISO 8601; only the day is used). - `event_date_end` (date-time): End date (ISO 8601; only the day is used). - `page_offset` (integer): Start position (items to skip). Default 0. - `page_limit` (integer): Items per page, up to 100. Default 25. **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/accounts/transactions?event_date_start=2026-10-01&event_date_end=2026-10-20' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "meta": { "total": 1, "limit": 25, "offset": 0 }, "data": [ { "eventDate": "2026-10-20T14:03:14.000Z", "id": "7c1d0f1e-5b0a-4a52-9a43-1d6f0b7f0c11", "status": "LIQUIDATED", "endToEndId": "E3187249520261020184600abcdEFGH12345", "txId": null, "creditDebitType": "DEBIT", "transactionType": "PIX", "transactionAmount": { "currency": "BRL", "available": 25.5, "amount": 25.5 }, "fee": 0.5, "description": "Repasse pedido 1042", "counterparty": { "name": "Fulano de Tal" } } ] } - creditDebitType: CREDIT is money in, DEBIT is money out. transactionAmount.available and amount carry the same value. #### GET /accounts/keys — List the account Pix keys The Pix keys the bank generated for your account. Whoever pays a key chooses the amount in their bank app. Keys are created in the bank panel; this API is read-only. Permission: pix.read → pix:read **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/accounts/keys' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "data": [ { "key": "9d2c41a7-6f0e-4b53-8a21-3c5e7b9f0d14", "keyType": "EVP", "branch": null, "accountNumber": null, "accountType": null, "name": "Sua Empresa LTDA", "tradeName": null, "taxIdNumber": null, "creationDate": "2026-10-20T18:45:32.244Z", "keyOwnershipDate": "2026-10-20T18:45:32.244Z", "status": "ACTIVE" } ] } ### Pix #### POST /pix/payments/dict — Start a Pix payment by Pix key Sends a Pix to a key (CPF, CNPJ, e-mail, phone or EVP, the random key). The amount is debited right away and the payment is accepted for processing (202). The outcome (LIQUIDATED or CANCELED) comes from the lookup by endToEndId or by idempotency key. If it is refused, the amount returns to the account. Permission: pix.write → pix:send **Headers** - `x-idempotency-key` (string, required): Unique request identifier (1 to 50 letters and digits). Repeating the same key returns the SAME payment, never paying twice. **Request body** - `pixKey` (string, required): The destination Pix key. - `pixKeyType` (string, required): CPF | CNPJ | EMAIL | PHONE | EVP - `payment.amount` (number, required): Amount in BRL, up to 2 decimals. - `payment.currency` (string): BRL. - `description` (string): Pix text, up to 140 characters. - `priority, paymentFlow, creditorDocument, expiration, endToEndId, ispbDeny` (—): Accepted and ignored (the bank chooses). **Code sample (curl)** curl -X POST 'https://bank.granseuk.com/api/v2/pix/payments/dict' \ -H 'Authorization: Bearer SEU_TOKEN' \ -H 'x-idempotency-key: pedido1042' \ -H 'Content-Type: application/json' \ -d '{"pixKey":"fulano@exemplo.com","pixKeyType":"EMAIL","payment":{"currency":"BRL","amount":25.5},"description":"Repasse pedido 1042"}' **202** — Accepted { "endToEndId": null, "eventDate": "2026-10-20T14:03:11.000Z", "id": 218394857201, "payment": { "currency": "BRL", "amount": 25.5 }, "type": "PIX", "transactionId": "7c1d0f1e-5b0a-4a52-9a43-1d6f0b7f0c11", "idempotencyKey": "pedido1042", "status": "PROCESSING", "fee": 0.5 } **400** — Business rule or invalid field (balance, limit, invalid key…). Nothing was debited. { "type": "onz-0008", "title": "Invalid request", "status": 400, "detail": "Saldo insuficiente", "instance": "/api/v2/pix/payments/dict", "statusCode": 400, "error": "insufficient_funds", "message": "Saldo insuficiente" } - endToEndId may be null in the 202: it appears as soon as the Pix goes on to the destination bank. Look it up by idempotency key or by transactionId. - id is a stable number; to look it up use endToEndId or transactionId. #### GET /pix/payments/{endToEndId} — Get a Pix by end-to-end id The full payment. Accepts the Pix endToEndId or the transactionId returned on creation. 404 if it is not a payment of your account. Permission: pix.read → pix:read **Path parameters** - `endToEndId` (string, required): The Pix endToEndId (or the transactionId). **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/pix/payments/E3187249520261020184600abcdEFGH12345' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "data": { "id": 218394857201, "transactionId": "7c1d0f1e-5b0a-4a52-9a43-1d6f0b7f0c11", "idempotencyKey": "pedido1042", "endToEndId": "E3187249520261020184600abcdEFGH12345", "pixKey": "fulano@exemplo.com", "transactionType": "PIX", "status": "LIQUIDATED", "errorCode": null, "localInstrument": null, "creditDebitType": "DEBIT", "createdAt": "2026-10-20T14:03:11.000Z", "settledAt": "2026-10-20T14:03:14.000Z", "creditorAccount": { "ispb": null, "issuer": null, "number": null, "accountType": null, "document": null, "name": "Fulano de Tal" }, "debtorAccount": { "ispb": null, "issuer": null, "number": null, "accountType": null, "document": null, "name": null }, "remittanceInformation": "Repasse pedido 1042", "txId": null, "payment": { "currency": "BRL", "amount": 25.5 }, "fee": 0.5, "refunds": [] } } **404** — Payment not found in this account { "type": "onz-0009", "title": "Pix not found", "status": 404, "detail": "Pagamento nao encontrado", "instance": "/api/v2/pix/payments/{endToEndId}", "statusCode": 404, "error": "not_found", "message": "Pagamento nao encontrado" } - status: PROCESSING, LIQUIDATED, CANCELED, REFUNDED or WAITING_APPROVAL. #### GET /pix/payments/idempotencyKey/{idempotencyKey} — Get a Pix by idempotency key The same payment, found by the x-idempotency-key you sent. Use it after a timeout to find out whether the request arrived. Permission: pix.read → pix:read **Path parameters** - `idempotencyKey` (string, required): The request idempotency key. **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/pix/payments/idempotencyKey/pedido1042' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "data": { "id": 218394857201, "transactionId": "7c1d0f1e-5b0a-4a52-9a43-1d6f0b7f0c11", "idempotencyKey": "pedido1042", "endToEndId": "E3187249520261020184600abcdEFGH12345", "pixKey": "fulano@exemplo.com", "transactionType": "PIX", "status": "PROCESSING", "errorCode": null, "localInstrument": null, "creditDebitType": "DEBIT", "createdAt": "2026-10-20T14:03:11.000Z", "settledAt": null, "creditorAccount": { "ispb": null, "issuer": null, "number": null, "accountType": null, "document": null, "name": "Fulano de Tal" }, "debtorAccount": { "ispb": null, "issuer": null, "number": null, "accountType": null, "document": null, "name": null }, "remittanceInformation": "Repasse pedido 1042", "txId": null, "payment": { "currency": "BRL", "amount": 25.5 }, "fee": 0.5, "refunds": [] } } #### GET /pix/payments/receipt/{endToEndId} — Get the Pix receipt as a PDF The payment receipt as a base64-encoded PDF (with the bank's branding). Accepts the endToEndId or the transactionId. Permission: pix.read → pix:read **Path parameters** - `endToEndId` (string, required): The Pix endToEndId (or the transactionId). **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/pix/payments/receipt/E3187249520261020184600abcdEFGH12345' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "data": { "pdf": "JVBERi0xLjQK…" } } **404** — Payment not found in this account { "type": "onz-0009", "title": "Pix not found", "status": 404, "detail": "Pagamento nao encontrado", "instance": "/api/v2/pix/payments/receipt/{endToEndId}", "statusCode": 404, "error": "not_found", "message": "Pagamento nao encontrado" } #### GET /pix/keys/{key} — Look up a Pix key What the DICT says about any Pix key: name, document (masked by the DICT itself) and bank. Use it to confirm the recipient before sending. If the bank's provider does not query the DICT, it answers 501 not_supported. Permission: pix.read → pix:read **Path parameters** - `key` (string, required): The Pix key (CPF, CNPJ, e-mail, phone or random). **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/pix/keys/{key}' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "name": "Fulano de Tal", "tradeName": null, "keyType": "EMAIL", "key": "fulano@exemplo.com", "document": "***.456.789-**", "ispb": "00000000", "ispb_reduced_name": "Banco Exemplo", "endToEndId": null } **404** — Key not found { "type": "onz-0009", "title": "Pix not found", "status": 404, "detail": "Chave Pix nao encontrada", "instance": "/api/v2/pix/keys/{key}", "statusCode": 404, "error": "not_found", "message": "Chave Pix nao encontrada" } ### Pix charges #### PUT /cob/{txid} — Create an immediate charge with a txid Creates a Pix charge (dynamic QR) with the txid you choose: 26 to 35 letters and digits. Repeating the PUT with the same txid returns the same charge. Each bank sets a minimum amount per charge (below it: 400 below_limit, with the minimum in the message). Permission: cob.write → pix:write **Path parameters** - `txid` (string, required): 26 to 35 letters and digits. **Request body** - `valor.original` (string, required): Amount in BRL as a dot-decimal string ("49.90"). - `calendario.expiracao` (integer): Validity in seconds, 60 to 2592000. Default 86400. - `devedor.nome, devedor.cpf, devedor.cnpj` (string): Who will pay (optional). - `solicitacaoPagador` (string): Text shown to the payer, up to 140 characters. **Code sample (curl)** curl -X PUT 'https://bank.granseuk.com/api/v2/cob/ABC123def456GHI789jkl012MNO345' \ -H 'Authorization: Bearer SEU_TOKEN' \ -H 'Content-Type: application/json' \ -d '{"calendario":{"expiracao":3600},"devedor":{"cpf":"12345678909","nome":"Fulano de Tal"},"valor":{"original":"49.90"},"solicitacaoPagador":"Pedido 1042"}' **201** — Created { "txid": "ABC123def456GHI789jkl012MNO345", "id": "0b6c2a0e-91a1-4e0e-8b73-8a0b6d3f1d22", "revisao": 0, "status": "ATIVA", "calendario": { "criacao": "2026-10-20T14:05:00.000Z", "expiracao": 3600 }, "devedor": { "nome": "Fulano de Tal", "cpf": "12345678909" }, "valor": { "original": "49.90", "modalidadeAlteracao": 0 }, "chave": null, "loc": null, "location": null, "solicitacaoPagador": "Pedido 1042", "infoAdicionais": [], "pixCopiaECola": "00020126…6304ABCD" } #### POST /cob — Create an immediate charge (generated txid) Same as the PUT, but the bank generates the txid and returns it in the response. Permission: cob.write → pix:write **Request body** - `valor.original` (string, required): Amount in BRL as a dot-decimal string ("49.90"). - `calendario.expiracao` (integer): Validity in seconds, 60 to 2592000. Default 86400. - `devedor, solicitacaoPagador` (object | string): As in the PUT. **Code sample (curl)** curl -X POST 'https://bank.granseuk.com/api/v2/cob' \ -H 'Authorization: Bearer SEU_TOKEN' \ -H 'Content-Type: application/json' \ -d '{"calendario":{"expiracao":3600},"valor":{"original":"49.90"},"solicitacaoPagador":"Pedido 1042"}' **201** — Created { "txid": "5f2c9d8e7a6b4c3d2e1f0a9b8c7d6e5f", "id": "0b6c2a0e-91a1-4e0e-8b73-8a0b6d3f1d22", "revisao": 0, "status": "ATIVA", "calendario": { "criacao": "2026-10-20T14:05:00.000Z", "expiracao": 3600 }, "devedor": { "nome": "Fulano de Tal", "cpf": "12345678909" }, "valor": { "original": "49.90", "modalidadeAlteracao": 0 }, "chave": null, "loc": null, "location": null, "solicitacaoPagador": "Pedido 1042", "infoAdicionais": [], "pixCopiaECola": "00020126…6304ABCD" } #### GET /cob/{txid} — Get an immediate charge The charge state. When paid, status is CONCLUIDA and the pix list carries the endToEndId. When money arrives, always confirm with this call; do not rely on an external notice alone. Permission: cob.read → pix:read **Path parameters** - `txid` (string, required): The charge txid. **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/cob/ABC123def456GHI789jkl012MNO345' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "txid": "ABC123def456GHI789jkl012MNO345", "status": "CONCLUIDA", "valor": { "original": "49.90" }, "pix": [ { "endToEndId": "E3187249520261020184600abcdEFGH12345", "valor": "49.90", "horario": "2026-10-20T14:07:41.000Z" } ] } **404** — Charge not found { "type": "onz-0009", "title": "Pix not found", "status": 404, "detail": "Cobranca nao encontrada", "instance": "/api/v2/cob/{txid}", "statusCode": 404, "error": "not_found", "message": "Cobranca nao encontrada" } - status: ATIVA (waiting), CONCLUIDA (paid), REMOVIDA_PELO_USUARIO_RECEBEDOR (cancelled), REMOVIDA_PELO_PSP (expired). ### Transfer between accounts #### POST /internal-transfers — Create a transfer between accounts Transfers to another account at this same bank, instantly and without going through Pix. The destination account is found by the holder's document (CPF or CNPJ), and the name you send must match the account: if any check fails, nothing is transferred. Repeating the same x-idempotency-key returns the same transfer. Permission: internal-transfer.write → transfers:write **Headers** - `x-idempotency-key` (string, required): Unique request identifier (1 to 50 letters and digits). **Request body** - `creditorAccount.document` (string, required): CPF or CNPJ of the destination account holder. - `creditorAccount.name` (string, required): Holder name. Must match the account. - `creditorAccount.number` (string): Optional: the destination account id, as an extra check. - `payment.amount` (number, required): Amount in BRL, up to 2 decimals. - `remittanceInformation` (string): Description, up to 200 characters. - `creditorAccount.issuer, creditorAccount.accountType, paymentFlow` (—): Accepted and ignored. **Code sample (curl)** curl -X POST 'https://bank.granseuk.com/api/v2/internal-transfers' \ -H 'Authorization: Bearer SEU_TOKEN' \ -H 'x-idempotency-key: pedido1042' \ -H 'Content-Type: application/json' \ -d '{"creditorAccount":{"document":"12345678909","name":"Fulano de Tal","number":"","accountType":"TRAN"},"payment":{"currency":"BRL","amount":100},"remittanceInformation":"Acerto do pedido 1042"}' **202** — Accepted { "data": { "id": 218394857401, "transactionId": "3d9a1c52-7e0b-4f1a-9c3d-6a2b8e4f5d10", "endToEndId": null, "status": "LIQUIDATED", "transactionType": "INTERNAL", "createdAt": "2026-10-20T14:20:00.000Z", "eventDate": "2026-10-20T14:20:00.000Z", "idempotencyKey": "acerto1042", "payment": { "currency": "BRL", "amount": 100 }, "creditorAccount": { "document": null, "name": "Fulano de Tal", "issuer": null, "number": "8b1e…", "accountType": "TRAN", "ispb": null }, "debtorAccount": { "document": null, "name": "Sua Empresa LTDA", "issuer": null, "number": "c24f…", "accountType": "TRAN", "ispb": null }, "remittanceInformation": "Acerto do pedido 1042", "refunds": [], "fee": 0 } } **404** — No account at this bank with that document (recipient_not_found) { "type": "onz-0009", "title": "Pix not found", "status": 404, "detail": "Não há conta neste banco com esse documento", "instance": "/api/v2/internal-transfers", "statusCode": 404, "error": "recipient_not_found", "message": "Não há conta neste banco com esse documento" } **400** — Name differs from the holder (recipient_name_mismatch), balance, limit… Nothing was transferred. { "type": "onz-0008", "title": "Invalid request", "status": 400, "detail": "O nome informado não confere com o titular da conta de destino. Nada foi transferido.", "instance": "/api/v2/internal-transfers", "statusCode": 400, "error": "recipient_name_mismatch", "message": "O nome informado não confere com o titular da conta de destino. Nada foi transferido." } - It does not go through Pix: the transfer is created already settled (LIQUIDATED) and endToEndId is null. #### GET /internal-transfers/{endToEndId} — Get a transfer between accounts The transfer by endToEndId (when there is one) or by the transactionId returned on creation. Permission: internal-transfer.read → transactions:read **Path parameters** - `endToEndId` (string, required): The endToEndId or the transactionId. **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/internal-transfers/E3187249520261020184600abcdEFGH12345' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "data": { "id": 218394857401, "transactionId": "3d9a1c52-7e0b-4f1a-9c3d-6a2b8e4f5d10", "status": "LIQUIDATED", "transactionType": "INTERNAL", "payment": { "currency": "BRL", "amount": 100 } } } #### GET /internal-transfers/idempotencyKey/{idempotencyKey} — Get a transfer by idempotency key The same transfer, found by the x-idempotency-key you sent. Permission: internal-transfer.read → transactions:read **Path parameters** - `idempotencyKey` (string, required): The request idempotency key. **Code sample (curl)** curl -X GET 'https://bank.granseuk.com/api/v2/internal-transfers/idempotencyKey/pedido1042' \ -H 'Authorization: Bearer SEU_TOKEN' **200** — Success { "data": { "id": 218394857401, "transactionId": "3d9a1c52-7e0b-4f1a-9c3d-6a2b8e4f5d10", "status": "LIQUIDATED", "transactionType": "INTERNAL", "payment": { "currency": "BRL", "amount": 100 } } }