# API Documentation Payment processing platform that enables stores to accept payments, process transfers, and integrate with e-commerce platforms. All API requests require Bearer token authentication via the Authorization header. ## Authentication All endpoints use the Authorization header with a Bearer token. There are two distinct keys: - Payment routes: Authorization: Bearer - Transfer and balance routes: Authorization: Bearer (withdrawal key) Both keys are available in the dashboard under Settings → Integrations. Using the wrong key for a route returns 403. ## Base URL Base URL: https://api.payoutbr.com All endpoints are versioned under /v1/. ## Standards and Formats - Currency: ISO 4217 (3-letter code, e.g., BRL, USD). Reference: https://en.wikipedia.org/wiki/ISO_4217 - Amounts: always sent in minor units (cents) as integer. Example: R$ 100.00 = 10000 - Dates: ISO 8601 in UTC (UTC+00:00). Example: 2026-01-15T16:51:42.782Z ## Enums Values accepted in payment creation and related routes: - method: PIX | BOLETO | CREDIT_CARD - currency: BRL (ISO 4217) - items[].type (productType): DIGITAL | PHYSICAL - payment.status: PENDING | PROCESSING | PAID | REFUSED | REFUNDED | MED | CHARGEDBACK - transfer.status: IN_QUEUE | IN_ANALYSIS | APPROVED | PROCESSING | COMPLETED | REFUSED | FAILED - pixKeyType: CPF | CNPJ | EMAIL | PHONE | EVP | COPYPASTE ## Store ### GET /v1/balance Returns the store's current financial balance. Requires the withdrawal key. Response (200): ```json { "available": 5000, "transfers": { "pending": 180 }, "reserve": { "pending": 320 }, "receivables": { "pending": 0 }, "anticipations": { "pending": 0 }, "todayPayments": 2000, "todayTransfers": 1000 } ``` Status codes: 200, 400, 403, 404 ### GET /v1/store-info Returns store details. Response (200): ```json { "id": "as9xk3l2p0q8w7e6r5t4y1", "name": "Store Example", "type": "PF", "taxId": "12345678901", "status": "ACTIVE", "currency": "BRL", "tenantId": "xyz4k8s2m9z1x7c6v5b3n0", "userId": "usr7h2g5f9d3s1a8p4o6i0", "userName": "John Doe", "userImage": null, "userEmail": "johndoe@email.com", "createdAt": "2026-01-10T14:22:31.120Z", "updatedAt": "2026-03-28T09:11:45.532Z", "rejectionReason": null } ``` Status codes: 200, 400, 403, 404 ## Payments ### POST /v1/payment Creates a new payment. Supports PIX, BOLETO, and CREDIT_CARD methods. ⚠️ Amount must always be sent in cents (integer). Request body (PIX example): ```json { "amount": 10000, "currency": "BRL", "method": "PIX", "description": "Order payment", "externalRef": "order_123456", "notificationUrl": "https://example.com/webhook", "ip": "192.168.1.1", "payer": { "name": "John Doe", "taxId": "12345678900", "email": "john.doe@example.com", "phone": "11999990000" }, "items": [{ "quantity": 1, "name": "Product", "price": 10000, "type": "PHYSICAL" }], "delivery": { "fee": 1000, "address": { "country": "BR", "state": "SP", "city": "São Paulo", "district": "Centro", "street": "Rua Exemplo", "number": "123", "complement": null, "zipCode": "01001-000" } }, "card": { "token": "", "installments": 1, "billingAddress": null }, "boleto": { "billingAddress": null }, "splits": ["split_id_001"], "metadata": { "provider": "my-platform", "orderId": "ord_123", "sellerTaxId": "98765432100", "sellerEmail": "seller@example.com", "checkoutUrl": null, "returnUrl": null, "shopUrl": null, "referrerLink": null, "extra": null } } ``` Response (200) — PIX example: ```json { "id": "pay_01HXYZ123ABC456DEF789", "amount": 10000, "method": "PIX", "currency": "BRL", "status": "PAID", "description": "Order payment", "installments": 1, "payer": { "name": "John Doe", "taxId": "12345678900", "email": "john.doe@example.com", "phone": "11999990000" }, "externalRef": "order_123456", "notificationUrl": "https://example.com/webhook", "metadata": null, "orderId": null, "paidAt": "2026-01-15T16:51:42.782Z", "refundedAt": null, "createdAt": "2026-01-15T13:44:25.838Z", "updatedAt": "2026-01-15T16:51:42.782Z", "data": { "method": "PIX", "copypaste": "00020101...", "e2e": "E1234567890123456789012345678901" }, "splits": [{ "amount": 10000, "currency": "BRL", "percent": 100, "storeId": "store_001", "splitId": null }], "items": [{ "quantity": 1, "name": "Product", "price": 10000, "type": "PHYSICAL" }], "delivery": { "fee": 1000, "address": { "country": "BR", "state": "SP", "city": "São Paulo", "district": "Centro", "street": "Rua Exemplo", "number": "123", "complement": null, "zipCode": "01001-000" } } } ``` data fields by method: - PIX: copypaste, e2e - CREDIT_CARD: message, cardHolder, cardNumber, cardExpMonth, cardExpYear - BOLETO: barcode Status codes: 200, 400, 403, 404 ### GET /v1/payment/:id Returns details of a specific payment. Response (200): ```json { "id": "z8k3f1x9a2m4q7w6t5r0", "currency": "BRL", "status": "PAID", "amount": 15990, "installments": 1, "method": "PIX", "orderId": "ord_7h3d92ksl1p0x", "description": "Compra de produto digital", "payer": { "name": "Maria Silva Santos", "email": "maria.silva@email.com", "phone": "11988887777", "taxId": "32165498700" }, "metadata": { "customerId": "cus_00192", "source": "checkout_v2" }, "feeAmount": 799, "feeFixed": 299, "feePercent": 3, "chkFeeAmount": 0, "config": null, "data": { "id": "pix_txn_4k2m9z1a0", "method": "PIX", "message": null, "e2e": "E1823610928374650918273645091827", "copypaste": "00020101021226850014br.gov.bcb.pix2563api.gateway.test/pix/8a7b6c5d-1234-5678-9abc-abcdef1234565204000053039865802BR5921GATEWAY DEMO6009SaoPaulo62070503***6304A1B2", "barcode": null, "digitableLine": null, "createdAt": "2026-02-10T14:21:33.102Z", "updatedAt": "2026-02-10T14:21:40.551Z" }, "splits": [ { "amount": 15191, "currency": "BRL", "percent": 9500, "storeId": "store_main_001", "splitId": "split_a1b2c3" }, { "amount": 799, "currency": "BRL", "percent": 500, "storeId": "z8k334535a2m4q7w6t5r0", "splitId": "ksh39d993939jfkfh" } ], "items": [{ "quantity": 1, "name": "Product", "price": 15990, "type": "DIGITAL" }], "paidAt": "2026-02-10T14:21:40.551Z", "refundedAt": null, "createdAt": "2026-02-10T14:21:33.102Z", "updatedAt": "2026-02-10T14:21:40.551Z" } ``` Status codes: 200, 400, 403, 404 ### POST /v1/payment/:id/refund Refunds a payment. No request body required. Response (200): ```json { "message": "success" } ``` Status codes: 200, 400, 403, 404 ## Card Tokenization Before creating a credit card payment, tokenize the card. Tokens use NaCl crypto_box_seal encryption and generated using the API key. Method 1 — HTML Script Tag (frontend-side): Include the /v1/scripts endpoint (tenant base URL) on the page, then call init/encrypt. Card fields for this method: number, holderName, expMonth (number), expYear (number), cvv. ```html ``` ```js const pk = "CHAVE_DE_API" try { const card = { number: "5555444433331111", holderName: "John Doe", expMonth: 8, expYear: 2027, cvv: "789", }; await Payout.init(pk); const token = await Payout.encrypt(card); console.log(token); } catch (err) { console.error(err); } ``` Method 2 — PaymentTokenizer Class (backend-side): Implement using libsodium. Card fields: number, holder, expMonth (MM), expYear (YYYY), cvv. ```ts import sodium from "https://cdn.jsdelivr.net/npm/libsodium-wrappers@0.8.0/+esm"; type CardDTO = { number: string; holder: string; expMonth: string; expYear: string; cvv: string; }; class PaymentTokenizer { publicKey = ""; initialized = false; async init(pk: string): Promise { if (!pk || typeof pk !== "string" || pk.trim() === "") { throw new Error("INVALID_PUBLIC_KEY"); } await sodium.ready; this.publicKey = pk; this.initialized = true; } async encrypt(card: CardDTO): Promise { if (!this.initialized || !this.publicKey) { throw new Error("TOKENIZER_NOT_INITIALIZED"); } const payload = { number: String(card.number).replace(/D/g, ""), holder: card.holder.trim(), expMonth: card.expMonth, expYear: card.expYear, cvv: String(card.cvv).replace(/D/g, "") }; const encrypted = sodium.crypto_box_seal( sodium.from_string(JSON.stringify(payload)), sodium.from_base64(this.publicKey) ); return sodium.to_base64(encrypted); } } ``` How to use? ```ts const tokenizer = new PaymentTokenizer(); await tokenizer.init("CHAVE_DE_API"); const token = await tokenizer.encrypt({ number: "4111111111111111", holder: "JOHN DOE", expMonth: "12", expYear: "2030", cvv: "123" }); ``` Using the token ```ts { "method": "CREDIT_CARD", "card": { "token": "", "installments": 1 } } ``` ## Transfers All transfer endpoints require the withdrawal key: Authorization: Bearer . ### POST /v1/transfer Creates a PIX transfer from the store balance. ⚠️ Amount must always be sent in cents (integer). - method: PIX. - pixKeyType: CPF, CNPJ, EMAIL, PHONE, EVP, COPYPASTE. PIX key examples by pixKeyType: - CPF: "12345678900" - CNPJ: "12345678000199" - EMAIL: "user@example.com" - PHONE: "+5511999990000" (format: DDI + DDD + número — must include country code, e.g. +55 for Brazil) - EVP: "123e4567-e89b-12d3-a456-426614174000" - COPYPASTE: "00020126580014br.gov.bcb.pix0136123e4567-e89b-12d3-a456-4266141740005204000053039865802BR5913Fulano de Tal6008BRASILIA62070503***6304E2CA" Request body: ```json { "amount": 5000, "method": "PIX", "pix": { "pixKey": "email@example.com", "pixKeyType": "EMAIL" }, "externalRef": "withdraw_001", "notificationUrl": "https://example.com/webhook/transfer" } ``` Response (200): ```json { "id": "pl19j5ed2d2cn97zaihko49giq7", "amount": 5000, "method": "PIX", "currency": "BRL", "status": "IN_QUEUE", "message": "", "externalRef": "withdraw_001", "notificationUrl": "https://example.com/webhook/transfer", "approvedAt": null, "refusedAt": null, "cancelledAt": null, "paidAt": null, "createdAt": "2026-01-19T17:17:34.295Z", "updatedAt": "2026-01-19T17:17:34.295Z", "data": { "method": "PIX", "pixKey": "email@example.com", "pixKeyType": "EMAIL", "e2e": null } } ``` Status codes: 200, 400, 403, 404 ### GET /v1/transfer/:id Returns details of a specific transfer. Response (200): ```json { "id": "pl19j5ed2d2cn97zaihko49giq7", "amount": 2500, "method": "PIX", "currency": "BRL", "status": "APPROVED", "message": "Transferência realizada com sucesso.", "externalRef": "withdraw_001", "notificationUrl": "https://example.com/webhook/transfer", "approvedAt": "2026-02-25T18:10:21.331Z", "refusedAt": null, "cancelledAt": null, "paidAt": "2026-02-25T18:10:21.331Z", "createdAt": "2026-02-25T18:09:58.102Z", "updatedAt": "2026-02-25T18:10:21.331Z", "data": { "method": "PIX", "pixKey": "cliente@email.com", "pixKeyType": "EMAIL", "e2e": "E1823610928374650918273645091827" } } ``` Transfer statuses: IN_QUEUE | IN_ANALYSIS | APPROVED | PROCESSING | COMPLETED | REFUSED | FAILED Status codes: 200, 400, 403, 404 ## Webhooks To increase security, webhooks may include a signature sent in the header X-Signature: , allowing validation of the authenticity of the received notification. This signature is generated by the platform using HMAC with SHA-256 over the webhook body (JSON), using a shared secret WEBHOOK_SECRET and encoded in Base64. The integrator can reproduce the same calculation using the same secret and payload; if the generated signature matches the one sent in the header, the webhook is considered legitimate and intact. If they differ, the request may have been altered or not sent by the platform. This validation is optional but strongly recommended for security. ## Timezone All date and time fields sent in webhooks use the standard ISO 8601 in the timezone UTC (UTC+00:00), ensuring consistency regardless of the integrator's timezone. To avoid discrepancies caused by local time or daylight saving time, it is recommended to keep values in UTC for storage and processing, converting to the local timezone only at the presentation layer. ⚠️ Polling on GET /v1/payment/:id is strictly prohibited. Status updates MUST be consumed via webhook. Repeated polling will trigger rate limiting and may result in temporary or permanent IP block in case of abuse. Webhook integration is mandatory to track payment and transfer status changes. ### Payment Webhook Triggered when a payment status changes. Payload is the payment object (same structure as GET /v1/payment/:id). Possible values for the status field are: PENDING - Payment created and awaiting confirmation. PROCESSING - Payment under processing or analysis. PAID - Payment successfully completed. REFUSED - Payment declined by issuer or antifraud system. REFUNDED - Payment fully or partially refunded. MED - Dispute under preliminary review, awaiting evidence. CHARGEDBACK - Dispute confirmed with payment reversal. PIX payment webhook example: ```json { "id": "pay_01HXYZ123ABC456DEF789", "amount": 10000, "method": "PIX", "currency": "BRL", "status": "PAID", "description": "Pagamento de teste via PIX", "installments": 1, "payer": { "name": "John Doe", "taxId": "12345678900", "email": "john.doe@example.com", "phone": "11999990000" }, "externalRef": "order_123456", "notificationUrl": "https://example-webhook.test/notifications", "metadata": null, "paidAt": "2026-01-15T16:51:42.782Z", "refundedAt": null, "createdAt": "2026-01-15T13:44:25.838Z", "updatedAt": "2026-01-15T16:51:42.782Z", "orderId": null, "data": { "method": "PIX", "copypaste": "00020101021226850014br.gov.bcb.pix2563api.gateway.test/pix/123e4567-e89b-12d3-a456-4266141740005204000053039865802BR5920GATEWAY TESTE6009SaoPaulo61080540900062070503***6304ABCD", "e2e": "E1234567890123456789012345678901" }, "splits": [ { "amount": 10000, "currency": "BRL", "percent": 100, "storeId": "store_test_001", "splitId": null } ], "items": [ { "quantity": 1, "name": "Produto Teste", "price": 1000, "type": "PHYSICAL" } ], "delivery": { "fee": 1500, "address": { "country": "BR", "state": "SP", "city": "São Paulo", "district": "Centro", "street": "Rua Exemplo", "number": "123", "complement": "Apto 45", "zipCode": "01001-000" } } } ``` CREDIT_CARD payment webhook example: ```json { "id": "pay_test_cc_01HZ9ABCDEF123456", "amount": 1000, "method": "CREDIT_CARD", "currency": "BRL", "status": "PAID", "description": "Compra de produto de teste", "installments": 3, "payer": { "name": "John Doe", "taxId": "12345678900", "email": "john.doe@example.com", "phone": "11999990000" }, "externalRef": "order_test_456789", "notificationUrl": "https://example-webhook.test/notifications", "metadata": null, "paidAt": null, "refundedAt": null, "createdAt": "2026-01-19T17:34:23.491Z", "updatedAt": "2026-01-19T17:34:23.491Z", "orderId": null, "data": { "method": "CREDIT_CARD", "message": "Pagamento aprovado com sucesso", "cardHolder": "JOHN DOE", "cardNumber": "411111******1111", "cardExpMonth": "12", "cardExpYear": "2028" }, "splits": [ { "amount": 1000, "currency": "BRL", "percent": 100, "storeId": "store_test_001", "splitId": null } ], "items": [ { "quantity": 1, "name": "Produto Teste", "price": 1000, "type": "PHYSICAL" } ], "delivery": { "fee": 1500, "address": { "country": "BR", "state": "SP", "city": "São Paulo", "district": "Centro", "street": "Rua Exemplo", "number": "123", "complement": "Apto 45", "zipCode": "01001-000" } } } ``` BOLETO payment webhook example: ```json { "id": "pay_test_boleto_01HZABC123456789", "amount": 1000, "method": "BOLETO", "currency": "BRL", "status": "PENDING", "description": "Compra de produto de teste", "installments": 1, "payer": { "name": "John Doe", "taxId": "12345678900", "email": "john.doe@example.com", "phone": "11999990000" }, "externalRef": "order_test_789456", "notificationUrl": "https://example-webhook.test/notifications", "metadata": null, "paidAt": null, "refundedAt": null, "createdAt": "2026-01-19T17:38:39.973Z", "updatedAt": "2026-01-19T17:38:39.973Z", "orderId": null, "data": { "method": "BOLETO", "barcode": "34191.79001 01043.510047 91020.150008 4 12340000001000" }, "splits": [ { "amount": 1000, "currency": "BRL", "percent": 100, "storeId": "store_test_001", "splitId": null } ], "items": [ { "quantity": 1, "name": "Produto Teste", "price": 1000, "type": "PHYSICAL" } ], "delivery": { "fee": 1500, "address": { "country": "BR", "state": "SP", "city": "São Paulo", "district": "Centro", "street": "Rua Exemplo", "number": "123", "complement": "Apto 45", "zipCode": "01001-000" } } } ``` ### Transfer Webhook Triggered when a transfer status changes. Payload is the transfer object (same structure as GET /v1/transfer/:id). Possible values for the status field are: IN_QUEUE - Transfer created and waiting for processing. IN_ANALYSIS - Transfer under analysis. APPROVED - Transfer approved (not paid). PROCESSING - Transfer being processed. COMPLETED - Transfer successfully completed (paid). REFUSED - Transfer refused. FAILED - Transfer processing failed. PIX transfer (saque) webhook example: ```json { "id": "pl19j5ed2d2cn97zaihko49giq7", "amount": 5000, "method": "PIX", "currency": "BRL", "status": "COMPLETED", "message": "Transferência realizada com sucesso.", "externalRef": "withdraw_001", "notificationUrl": "https://example.com/webhook/transfer", "approvedAt": "2026-02-25T18:10:21.331Z", "refusedAt": null, "cancelledAt": null, "paidAt": "2026-02-25T18:10:25.512Z", "createdAt": "2026-02-25T18:09:58.102Z", "updatedAt": "2026-02-25T18:10:25.512Z", "data": { "method": "PIX", "pixKey": "email@example.com", "pixKeyType": "EMAIL", "e2e": "E1823610928374650918273645091827" } } ``` ## Error Responses Response (4xx): ```json { "message": "The user does not have permission for this operation." } ``` Response (400 with details): ```json { "message": "Validation error.", "error": { } } ``` HTTP status codes: - 200 — success - 400 — bad request / validation error - 403 — forbidden / missing authorization - 404 — resource not found