# Aruba — Documentação completa da API de pagamentos > API REST da Aruba para criar cobranças PIX (Brasil, BRL), consultar o status e receber webhooks. Valores e saldo em reais. Fonte: https://docs.arubabr.com · Base da API: https://api.arubabr.com · Índice: https://docs.arubabr.com/llms.txt --- ## Regras para assistentes de código Siga estas regras ao gerar código de integração com a Aruba. Todas vêm da documentação abaixo. 1. **API Key só no servidor.** O header é `X-API-Key` (chave `pk_live_…`). Guarde em variável de ambiente ou cofre de segredos. Nunca no front, no bundle do navegador ou no repositório. 2. **Criar cobrança:** `POST https://api.arubabr.com/api/v1/direct-payments`, chamado pelo servidor. `amount` é **inteiro em centavos de real** (`9990` = R$ 99,90) e `paymentMethod` é `"pix"`. Não existe campo de moeda: a API responde 400 a campos desconhecidos. 3. **Sem retry automático na criação.** Cada chamada cria uma cobrança nova (não há chave de idempotência). Em erro ou timeout, não repita sozinho. 4. **Guarde o `transaction_id`** da resposta junto do pedido. Ele é a chave para webhook e consulta. 5. **Pago = `AUTHORIZED`.** Libere o pedido só quando `GET https://api.arubabr.com/api/v1/payments/{transaction_id}/status` devolver `data.status = "AUTHORIZED"`. O corpo do webhook **não é prova de pagamento**: use-o como gatilho e confirme sempre na consulta. A liberação precisa ser idempotente (por `transaction_id` + status). Trate `REFUNDED`, `CHARGEBACK` e `IN_DISPUTE` mesmo em pedidos já entregues. 6. **Status da raiz.** Use `data.status`; `payment_data.status` é a foto da criação e pode continuar `PENDING`. 7. **Valores.** `amount` na criação é em centavos; `total_value`, `fee` e `net_value` na resposta, na consulta e no webhook vêm em reais, em decimal (`99.9` = R$ 99,90). 8. **PIX:** `customer.document` (CPF ou CNPJ válido, só números) é obrigatório. Mostre `payment_data.pix_key` como copia-e-cola e gere o QR Code a partir dele. Não existe status de expiração: controle o prazo do pedido do seu lado e gere uma nova cobrança depois dele. 9. **Webhook:** cadastrado no painel (Integração → Webhooks) com os eventos desejados; o corpo traz `event` (`transaction.paid` = `AUTHORIZED`). Responda `2xx` rápido: são 3 tentativas, 15 segundos entre elas. A Aruba não assina o corpo: autentique o endpoint com Basic Auth ou Bearer Token do cadastro e confirme na consulta. 10. **Formatos:** telefone em E.164 (`+5511999999999`); `birthDate` em `DD/MM/AAAA`; CPF/CNPJ só com números. `payment_method` vem em minúsculas na criação e em maiúsculas na consulta e no webhook. 11. **Limite de requisições:** 100 a cada 10 segundos por IP (HTTP 429). Faça polling a cada 5 a 15 segundos, com limite de tempo. 12. **Não invente** endpoints, campos, status ou eventos que não estejam nesta documentação. --- ## Sumário - **Começar:** Visão geral · Início rápido · Autenticação - **Cobranças:** Criar cobrança · PIX - **Depois do pagamento:** Consultar status · Webhooks · Status da transação - **Referência:** Erros · Valores e limites · Checklist de produção --- ## API de pagamentos da Aruba Crie cobranças PIX a partir do seu sistema e receba a confirmação por webhook. REST, JSON e autenticação por API Key. > **Nota — Arquivos para IA** > > Vai integrar com um assistente de código (Claude, ChatGPT, Cursor, Copilot…)? Passe para ele [docs.arubabr.com/llms-full.txt](https://docs.arubabr.com/llms-full.txt): é esta documentação inteira em Markdown, com as regras que o código precisa seguir. O índice no padrão llms.txt está em [docs.arubabr.com/llms.txt](https://docs.arubabr.com/llms.txt). Veja [Para IA](https://docs.arubabr.com/#para-ia). ### Como funciona 1. **Seu servidor cria a cobrança** — `POST /api/v1/direct-payments` com valor, método e comprador, autenticado pela API Key. 2. **O comprador paga** — Você mostra o que veio em `payment_data`: o código PIX copia-e-cola e o QR Code. 3. **A Aruba avisa** — Webhook no seu servidor. A venda está paga quando o status é `AUTHORIZED`. A criação devolve a cobrança com status `PENDING`. A confirmação chega depois, quando o banco do comprador conclui o pagamento: por webhook ou pela consulta de status. ### Recursos da API - **PIX** (BRASIL, BRL): Copia-e-cola e QR Code no app do banco. `paymentMethod: "pix"` — https://docs.arubabr.com/llms/pix.md - **Webhooks** (AVISOS, HTTP POST): Avisos de pagamento, estorno, disputa e outros eventos, enviados ao seu servidor. — https://docs.arubabr.com/llms/webhooks.md ### Endereço da API **Base URL** ``` https://api.arubabr.com ``` Requisições e respostas usam JSON. Envie `Content-Type: application/json` nas requisições com corpo. ### Endpoints | Método | Caminho | Autenticação | Uso | | --- | --- | --- | --- | | `POST` | [`/api/v1/direct-payments`](https://docs.arubabr.com/llms/criar-cobranca.md) | Header `X-API-Key` | Criar uma cobrança | | `GET` | [`/api/v1/payments/{transaction_id}/status`](https://docs.arubabr.com/llms/consultar-status.md) | Nenhuma | Consultar o status de uma transação | ### Formato das respostas Toda resposta tem o campo `hasError`. Com sucesso, os dados vêm em `data`; com erro, a mensagem vem em `error` (veja [Erros](https://docs.arubabr.com/llms/erros.md)). **Sucesso** ```json { "hasError": false, "data": { "transaction_id": "7KQ2M9XA4T1B", "status": "PENDING" } } ``` **Erro** ```json { "hasError": true, "error": "API key não fornecida. Envie a chave no header X-API-Key", "errorFields": [], "statusCode": 401, "timestamp": "2026-10-23T15:19:01.612Z", "path": "/api/v1/direct-payments" } ``` ### Conceitos - **Transação.** Cada cobrança criada gera uma transação, identificada por `transaction_id`. Guarde esse valor junto com o seu pedido: é ele que liga a criação, a consulta de status e o webhook. - **Valores.** Na criação, `amount` é um inteiro em centavos de real. Nas respostas, os valores vêm em unidades decimais (`99.9` = R$ 99,90). Detalhes em [Valores e limites](https://docs.arubabr.com/llms/limites.md). - **Produção.** As chaves de API são de produção (`pk_live_…`) e não existe modo de teste separado: toda cobrança criada é real. Para testar a integração, crie um PIX de valor baixo e pague você mesmo. --- ## Início rápido Sua primeira cobrança PIX em quatro passos. Esse é o fluxo inteiro de uma integração. 1. **Gere uma API Key** — No painel da Aruba, abra **Integração → API Keys** e clique em **Nova API Key**. Copie a chave (`pk_live_…`) na hora: ela aparece uma única vez. Guarde-a numa variável de ambiente do seu servidor, por exemplo `ARUBA_API_KEY`. 2. **Crie a cobrança** — Chame o endpoint de cobrança a partir do seu servidor. `amount` vai em centavos: `9990` = R$ 99,90. **cURL** ```bash curl -X POST https://api.arubabr.com/api/v1/direct-payments \ -H "Content-Type: application/json" \ -H "X-API-Key: $ARUBA_API_KEY" \ -d '{ "amount": 9990, "description": "Pedido 1234", "paymentMethod": "pix", "customer": { "name": "João da Silva", "email": "joao@exemplo.com", "document": "12345678909" } }' ``` **Node.js** ```javascript const res = await fetch("https://api.arubabr.com/api/v1/direct-payments", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.ARUBA_API_KEY, }, body: JSON.stringify({ amount: 9990, // R$ 99,90 em centavos description: "Pedido 1234", paymentMethod: "pix", customer: { name: "João da Silva", email: "joao@exemplo.com", document: "12345678909", }, }), }); const body = await res.json(); if (!res.ok) throw new Error(body.error); const { transaction_id, payment_data } = body.data; // Salve transaction_id no seu pedido antes de seguir. ``` **PHP** ```php $payload = [ "amount" => 9990, // R$ 99,90 em centavos "description" => "Pedido 1234", "paymentMethod" => "pix", "customer" => [ "name" => "João da Silva", "email" => "joao@exemplo.com", "document" => "12345678909", ], ]; $ch = curl_init("https://api.arubabr.com/api/v1/direct-payments"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Content-Type: application/json", "X-API-Key: " . getenv("ARUBA_API_KEY"), ], CURLOPT_POSTFIELDS => json_encode($payload), ]); $body = json_decode(curl_exec($ch), true); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http >= 400) throw new Exception($body["error"]); $transactionId = $body["data"]["transaction_id"]; // salve no seu pedido ``` **Resposta · 201 Created** ```json { "hasError": false, "data": { "transaction_id": "7KQ2M9XA4T1B", "total_value": 99.9, "status": "PENDING", "email": "joao@exemplo.com", "payment_method": "pix", "payment_data": { "expiration_date": null, "payment_id": "c1a7e0b2-5d3f-4e8a-9b61-0f2d7c4e9a13", "pix_key": "00020126580014br.gov.bcb.pix0136…6304A1B2", "status": "PENDING", "status_detail": "WAITING_PAYMENT", "total_transaction_value": 99.9 } } } ``` 3. **Mostre o PIX ao comprador** — `payment_data.pix_key` é o código copia-e-cola. Mostre-o com um botão de copiar e gere o QR Code a partir dele com a biblioteca de QR Code que preferir. Envie ao navegador só o que ele precisa exibir, nunca a API Key. 4. **Confirme o pagamento** — Cadastre a URL do seu servidor em **Integração → Webhooks**. Quando o PIX for pago, a Aruba envia um `POST` com `"status": "AUTHORIZED"`. Confirme na consulta de status e libere o pedido. **Consulta de status** ```bash curl https://api.arubabr.com/api/v1/payments/7KQ2M9XA4T1B/status ``` > **Atenção — Só AUTHORIZED é pagamento confirmado** > > A resposta da criação traz a cobrança ainda pendente. Libere o pedido apenas quando o seu servidor receber ou consultar o status `AUTHORIZED`. ### Próximos passos - **Autenticação**: Como criar, guardar e revogar API Keys. — https://docs.arubabr.com/llms/autenticacao.md - **Criar cobrança**: Todos os campos do corpo e da resposta. — https://docs.arubabr.com/llms/criar-cobranca.md - **Webhooks**: Payload, eventos, retentativas e idempotência. — https://docs.arubabr.com/llms/webhooks.md --- ## Autenticação A criação de cobranças é autenticada por API Key, enviada no header `X-API-Key`. Cada chave pertence a uma conta: as cobranças criadas com ela entram nessa conta. ### Criar uma API Key 1. No painel da Aruba, abra **Integração → API Keys**. 2. Clique em **Nova API Key**, dê um nome (3 a 100 caracteres) e, se quiser, uma descrição (até 255). 3. Copie a chave exibida. **Ela aparece uma única vez**. Se perder, crie outra. A chave tem o formato `pk_live_` seguido de 48 caracteres hexadecimais em minúsculas. ### Enviar a chave **Cabeçalhos da requisição** ```http POST /api/v1/direct-payments HTTP/1.1 Host: api.arubabr.com Content-Type: application/json X-API-Key: pk_live_… ``` A [consulta de status](https://docs.arubabr.com/llms/consultar-status.md) não usa API Key. ### Gerenciar chaves - **Limite:** até 10 chaves ativas por conta. - **Pausar:** em **Editar** (ou no menu da chave), mude o status para pausada. A API passa a recusar a chave até você reativá-la. - **Deletar:** remove a chave de vez. Chamadas com ela passam a receber `401`. ### Boas práticas - Use a chave só no servidor. Nunca a coloque em front-end, app mobile ou repositório de código. - Guarde-a em variável de ambiente ou num cofre de segredos. - Crie uma chave por integração: dá para trocar ou pausar uma sem afetar as outras. - Se suspeitar de vazamento, delete a chave e crie outra. ### Erros de autenticação Problemas de autenticação respondem HTTP `401`, com a mensagem em `error`: | Mensagem | Causa | | --- | --- | | `API key não fornecida. Envie a chave no header X-API-Key` | O header não foi enviado. | | `Formato de API key inválido` | A chave não tem o formato `pk_live_` + 48 hexadecimais. Confira se foi copiada inteira, sem espaços ou quebras de linha. | | `API key inválida` | Não existe chave com esse valor (por exemplo, ela foi deletada). | | `API key está inativa ou revogada` | A chave está pausada. Reative em **Integração → API Keys**. | | `Seller está bloqueado para receber pagamentos` | A conta está bloqueada. Fale com o suporte. | --- ## Criar cobrança **Endpoint:** `POST /api/v1/direct-payments` · Header `X-API-Key` Cria uma cobrança PIX para um comprador, sem produto cadastrado na Aruba. A resposta traz o código copia-e-cola em `payment_data`. ### Corpo da requisição | Campo | Tipo | Obrigatório | Descrição | | --- | --- | --- | --- | | `amount` | inteiro | **obrigatório** | Valor em **centavos de real**, a partir de `1`. Ex.: `9990` = R$ 99,90. Não envie valores decimais em reais. | | `description` | string | **obrigatório** | Descrição da cobrança, de 3 a 255 caracteres. | | `paymentMethod` | string | **obrigatório** | `pix`. | | `customer` | objeto | **obrigatório** | Dados do comprador (abaixo). | > **Atenção — Campos desconhecidos são recusados** > > A API responde `400` se o corpo tiver um campo que ela não conhece (por exemplo `currency`). Envie só os campos desta página. #### Objeto `customer` | Campo | Tipo | Obrigatório | Descrição | | --- | --- | --- | --- | | `name` | string | **obrigatório** | Nome completo, de 3 a 128 caracteres. | | `email` | string | **obrigatório** | E-mail válido do comprador. | | `document` | string | **obrigatório** | CPF (11 dígitos) ou CNPJ (14 dígitos) válido, só números. | | `phone` | string | opcional | Formato E.164, com `+` e código do país, ex.: `+5511999999999`. Precisa ser um número válido. | | `birthDate` | string | opcional | Data de nascimento no formato `DD/MM/AAAA`, ex.: `15/01/1990`. O formato `AAAA-MM-DD` é recusado. | | `address` | objeto | opcional | Endereço do comprador (abaixo). | | `utm` | objeto | opcional | Parâmetros de rastreamento da venda (abaixo). | #### Objeto `customer.address` Se enviar o endereço, os campos marcados como obrigatórios passam a ser exigidos. | Campo | Tipo | Obrigatório | Descrição | | --- | --- | --- | --- | | `zipCode` | string | **obrigatório** | CEP com 8 dígitos, sem hífen. | | `street` | string | **obrigatório** | Logradouro, de 3 a 128 caracteres. | | `district` | string | **obrigatório** | Bairro, de 3 a 128 caracteres. | | `city` | string | **obrigatório** | Cidade, de 3 a 128 caracteres. | | `state` | string | **obrigatório** | UF, ex.: `SP`. | | `number` | string | opcional | Número, de 1 a 6 caracteres. | | `complement` | string | opcional | Complemento, de 1 a 48 caracteres. | #### Objeto `customer.utm` | Campo | Tipo | Descrição | | --- | --- | --- | | `source` | string | `utm_source`, até 128 caracteres. | | `medium` | string | `utm_medium`, até 128 caracteres. | | `campaign` | string | `utm_campaign`, até 128 caracteres. | | `term` | string | `utm_term`, até 128 caracteres. | | `content` | string | `utm_content`, até 128 caracteres. | | `src` | string | Parâmetro `src` usado na integração com a Utmify, até 2048 caracteres. | | `sck` | string | Parâmetro `sck` usado na integração com a Utmify, até 256 caracteres. | ### Exemplo completo **cURL** ```bash curl -X POST https://api.arubabr.com/api/v1/direct-payments \ -H "Content-Type: application/json" \ -H "X-API-Key: $ARUBA_API_KEY" \ -d '{ "amount": 15000, "description": "Assinatura anual", "paymentMethod": "pix", "customer": { "name": "Maria Souza", "email": "maria@exemplo.com", "document": "12345678909", "phone": "+5511999999999", "birthDate": "15/01/1990", "address": { "zipCode": "01310100", "street": "Avenida Paulista", "number": "1000", "complement": "Sala 101", "district": "Bela Vista", "city": "São Paulo", "state": "SP" }, "utm": { "source": "google", "medium": "cpc", "campaign": "lancamento" } } }' ``` **Node.js** ```javascript const res = await fetch("https://api.arubabr.com/api/v1/direct-payments", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.ARUBA_API_KEY, }, body: JSON.stringify({ amount: 15000, description: "Assinatura anual", paymentMethod: "pix", customer: { name: "Maria Souza", email: "maria@exemplo.com", document: "12345678909", phone: "+5511999999999", birthDate: "15/01/1990", address: { zipCode: "01310100", street: "Avenida Paulista", number: "1000", complement: "Sala 101", district: "Bela Vista", city: "São Paulo", state: "SP", }, utm: { source: "google", medium: "cpc", campaign: "lancamento" }, }, }), }); const body = await res.json(); if (!res.ok) throw new Error(`${body.error} ${body.errorFields.join("; ")}`); ``` **PHP** ```php $payload = [ "amount" => 15000, "description" => "Assinatura anual", "paymentMethod" => "pix", "customer" => [ "name" => "Maria Souza", "email" => "maria@exemplo.com", "document" => "12345678909", "phone" => "+5511999999999", "birthDate" => "15/01/1990", "address" => [ "zipCode" => "01310100", "street" => "Avenida Paulista", "number" => "1000", "complement" => "Sala 101", "district" => "Bela Vista", "city" => "São Paulo", "state" => "SP", ], "utm" => ["source" => "google", "medium" => "cpc", "campaign" => "lancamento"], ], ]; $ch = curl_init("https://api.arubabr.com/api/v1/direct-payments"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json", "X-API-Key: " . getenv("ARUBA_API_KEY")], CURLOPT_POSTFIELDS => json_encode($payload), ]); $body = json_decode(curl_exec($ch), true); curl_close($ch); ``` ### Resposta Com sucesso, a API responde `201 Created`: | Campo | Tipo | Descrição | | --- | --- | --- | | `transaction_id` | string | Identificador da transação na Aruba. Use na consulta de status e para reconhecer o webhook. | | `total_value` | número | Valor cobrado em reais (não em centavos). Ex.: `99.9`. | | `status` | string | Status inicial da cobrança, normalmente `PENDING`. | | `email` | string | E-mail do comprador, em minúsculas. | | `payment_method` | string | O método enviado, em minúsculas: `pix`. | | `payment_data` | objeto | O que o comprador precisa para pagar. Veja [PIX](https://docs.arubabr.com/llms/pix.md). | > **Importante — Cada chamada cria uma cobrança nova** > > A criação não tem chave de idempotência. Se a requisição falhar por timeout ou erro de rede, não repita automaticamente: confira em **Vendas**, no painel, se a cobrança foi criada antes de gerar outra. ### Erros mais comuns | HTTP | Mensagem | O que fazer | | --- | --- | --- | | 401 | `API key não fornecida…` e similares | Veja [Autenticação](https://docs.arubabr.com/llms/autenticacao.md). | | 400 | `Erro na validação dos campos` | Leia `errorFields`: ele lista cada campo com problema. | | 400 | `document é obrigatório para este método de pagamento` | Envie o CPF ou CNPJ do comprador. | | 400 | `document deve ser um CPF ou CNPJ válido (somente números)` | Confira os dígitos do documento. | | 400 | `Você ainda não possui documentos validados para gerar pagamentos` | Conclua a validação de documentos da sua conta no painel. | A lista completa está em [Erros](https://docs.arubabr.com/llms/erros.md). --- ## PIX Cobrança em reais paga com copia-e-cola ou QR Code no app do banco. País **BR** · Moeda **BRL** · paymentMethod **"pix"** ### Requisição | Campo | Regra no PIX | | --- | --- | | `amount` | Centavos de real. `9990` = R$ 99,90. | | `customer.document` | **obrigatório** CPF ou CNPJ válido, só números. | **cURL** ```bash curl -X POST https://api.arubabr.com/api/v1/direct-payments \ -H "Content-Type: application/json" \ -H "X-API-Key: $ARUBA_API_KEY" \ -d '{ "amount": 9990, "description": "Pedido 1234", "paymentMethod": "pix", "customer": { "name": "João da Silva", "email": "joao@exemplo.com", "document": "12345678909" } }' ``` **Node.js** ```javascript const res = await fetch("https://api.arubabr.com/api/v1/direct-payments", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.ARUBA_API_KEY }, body: JSON.stringify({ amount: 9990, description: "Pedido 1234", paymentMethod: "pix", customer: { name: "João da Silva", email: "joao@exemplo.com", document: "12345678909" }, }), }); const { data } = await res.json(); // Para o front: só o copia-e-cola e o valor return { transactionId: data.transaction_id, pix: data.payment_data.pix_key, valor: data.total_value }; ``` **PHP** ```php $ch = curl_init("https://api.arubabr.com/api/v1/direct-payments"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json", "X-API-Key: " . getenv("ARUBA_API_KEY")], CURLOPT_POSTFIELDS => json_encode([ "amount" => 9990, "description" => "Pedido 1234", "paymentMethod" => "pix", "customer" => ["name" => "João da Silva", "email" => "joao@exemplo.com", "document" => "12345678909"], ]), ]); $data = json_decode(curl_exec($ch), true)["data"]; curl_close($ch); $copiaECola = $data["payment_data"]["pix_key"]; ``` ### Resposta Campos de `payment_data` no PIX: | Campo | Tipo | Descrição | | --- | --- | --- | | `pix_key` | string | Código PIX copia-e-cola. Mostre com botão de copiar e gere o QR Code a partir dele. | | `expiration_date` | string \| null | Validade informada pelo processador, em ISO 8601. Pode vir `null`. | | `payment_id` | string | Identificador da cobrança no processador. Para tudo na Aruba, use o `transaction_id`. | | `status`, `status_detail` | string | Situação no momento da criação (`PENDING` / `WAITING_PAYMENT`). Não muda depois: o status que vale é o da raiz, na consulta ou no webhook. | | `total_transaction_value` | número | Valor em reais. | Dependendo do processador, `payment_data` pode trazer outros campos. Ignore os que você não usa. ### Tela de pagamento - Mostre o valor, o código copia-e-cola com botão **Copiar** e o QR Code gerado a partir de `pix_key`. - Enquanto a tela estiver aberta, consulte o status a cada 5 a 15 segundos para trocar a mensagem quando o pagamento for confirmado. A consulta não exige API Key e pode ser feita pelo navegador. - Essa consulta no navegador serve só para a experiência do comprador. A liberação do pedido acontece no seu servidor (webhook + consulta). **JavaScript no navegador** ```javascript async function aguardarPagamento(transactionId, { intervalo = 10000, limite = 30 * 60 * 1000 } = {}) { const url = `https://api.arubabr.com/api/v1/payments/${transactionId}/status`; const fim = Date.now() + limite; while (Date.now() < fim) { const res = await fetch(url); if (res.ok) { const { data } = await res.json(); if (data.status === "AUTHORIZED") return "pago"; if (["REJECTED", "CANCELED"].includes(data.status)) return "nao-pago"; } await new Promise((r) => setTimeout(r, intervalo)); } return "tempo-esgotado"; } ``` ### Vencimento > **Atenção — Não existe status de expiração** > > Um PIX vencido e não pago pode continuar `PENDING` ou mudar para `REJECTED` ou `CANCELED`, conforme o processador. Controle o prazo do pedido do seu lado e, se o comprador voltar depois, gere uma nova cobrança. --- ## Consultar status **Endpoint:** `GET /api/v1/payments/{transaction_id}/status` · Sem autenticação Devolve o status atual da transação e os dados de pagamento gravados na criação. Não exige API Key: pode ser chamada pelo seu servidor, para confirmar um webhook, e pelo navegador, para atualizar a tela do comprador. ### Parâmetro | Parâmetro | Em | Descrição | | --- | --- | --- | | `transaction_id` | caminho | O `transaction_id` devolvido na criação da cobrança. | ### Requisição **cURL** ```bash curl https://api.arubabr.com/api/v1/payments/7KQ2M9XA4T1B/status ``` **Node.js** ```javascript const res = await fetch(`https://api.arubabr.com/api/v1/payments/${transactionId}/status`); const body = await res.json(); if (!res.ok) throw new Error(body.error); // ex.: "Pedido não encontrado!" console.log(body.data.status); // "PENDING", "AUTHORIZED"… ``` **PHP** ```php $url = "https://api.arubabr.com/api/v1/payments/" . urlencode($transactionId) . "/status"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $body = json_decode(curl_exec($ch), true); curl_close($ch); $status = $body["data"]["status"] ?? null; // "PENDING", "AUTHORIZED"… ``` ### Resposta **PIX · 200 OK** ```json { "hasError": false, "data": { "transaction_id": "7KQ2M9XA4T1B", "total_value": 99.9, "fee": 4.49, "net_value": 95.41, "status": "AUTHORIZED", "product": null, "payment_method": "PIX", "producer": null, "payment_data": { "pix_key": "00020126580014br.gov.bcb.pix0136…6304A1B2", "expiration_date": null, "payment_id": "c1a7e0b2-5d3f-4e8a-9b61-0f2d7c4e9a13", "status": "PENDING", "status_detail": "WAITING_PAYMENT", "total_transaction_value": 99.9 } } } ``` Os valores do exemplo são ilustrativos: a taxa depende do plano da sua conta. | Campo | Tipo | Descrição | | --- | --- | --- | | `transaction_id` | string | Identificador da transação. | | `status` | string | Status atual. É o campo que vale; veja [Status da transação](https://docs.arubabr.com/llms/status.md). | | `total_value` | número | Valor da transação em reais. | | `fee` | número | Taxa da Aruba, em reais. | | `net_value` | número | Valor líquido para você, em reais. | | `payment_method` | string | Método **em maiúsculas**: `PIX`. | | `product`, `producer` | objeto \| null | `null` nas cobranças criadas pela API. Vêm preenchidos nas vendas de produto feitas pelo checkout da Aruba. | | `payment_data` | objeto | Dados gravados na criação, como o `pix_key`. | > **Atenção — Use o status da raiz** > > No PIX, `payment_data.status` é a foto do momento da criação e continua `PENDING` mesmo depois do pagamento. O status atual é sempre `data.status`. ### Erros | HTTP | Mensagem | Causa | | --- | --- | --- | | 400 | `Pedido não encontrado!` | Não existe transação com esse `transaction_id`. | ### Polling - Consulte a cada 5 a 15 segundos, com um limite de tempo, e pare quando o status deixar de ser `PENDING`. - Polling é apoio. Para liberar pedidos, use o [webhook](https://docs.arubabr.com/llms/webhooks.md) e confirme com esta consulta. --- ## Webhooks A Aruba avisa o seu servidor com um `POST` em JSON quando uma transação sua é atualizada. Use o aviso como gatilho e confirme o status na consulta antes de liberar o pedido. ### Cadastrar a URL 1. No painel da Aruba, abra **Integração → Webhooks** e clique em **Novo Webhook**. 2. Informe um nome e a **URL de destino**. Use HTTPS. 3. Escolha os **eventos** que esse webhook deve receber (veja a tabela abaixo). É preciso marcar ao menos um. 4. Se o seu endpoint exige autenticação, escolha o **tipo de autenticação**: *Basic Auth* (usuário e senha) ou *Bearer Token*. Sem autenticação, deixe em *Nenhuma*. 5. Clique em **Cadastrar**. O webhook já nasce ativo. - Você pode cadastrar mais de uma URL (o painel aceita até 10). Cada URL ativa recebe os eventos que escolheu. - Em **Editar**, dá para trocar URL, eventos e autenticação. Com **Pausar**, o webhook deixa de receber disparos até ser ativado de novo. - Os avisos cobrem todas as transações da sua conta, não só as criadas pela API. Ignore os `transaction_id` que a sua integração não conhece. ### Eventos Cada aviso leva o nome do evento no campo `event`. O webhook só recebe os eventos que foram marcados nele. | Evento | Status | Descrição | | --- | --- | --- | | `transaction.pending` | `PENDING` | Venda criada, aguardando pagamento. | | `transaction.processing` | `PROCESSING` | Venda em processamento. | | `transaction.paid` | `AUTHORIZED` | Pagamento aprovado. | | `transaction.refunded` | `REFUNDED` | Venda reembolsada. | | `transaction.canceled` | `CANCELED` | Venda cancelada. | | `transaction.rejected` | `REJECTED` | Pagamento recusado. | | `transaction.chargeback` | `CHARGEBACK` | Chargeback recebido. | | `transaction.dispute` | `IN_DISPUTE` | Venda em disputa. | > **Atenção — Marque ao menos transaction.paid** > > Para liberar pedidos, o webhook precisa receber `transaction.paid`. Para tratar devoluções, inclua também `transaction.refunded`, `transaction.chargeback` e `transaction.dispute`. ### Quando a Aruba envia - Quando o processador informa uma atualização da transação: pagamento aprovado, recusa, cancelamento, estorno, chargeback, disputa e atualizações de pendência. - Quando a equipe da Aruba aprova uma transação manualmente. - Não há aviso na criação da cobrança. Uma falha ao gerar a cobrança (`FAILED`) também não gera aviso: nesse caso a própria criação já respondeu erro. - O mesmo status pode chegar mais de uma vez, por exemplo duas atualizações seguidas com `PENDING`. ### Requisição enviada `POST` para a sua URL, com `Content-Type: application/json` e este corpo: **PIX · transaction.paid** ```json { "event": "transaction.paid", "transaction_id": "7KQ2M9XA4T1B", "total_value": 99.9, "fee": 4.49, "net_value": 95.41, "status": "AUTHORIZED", "product": null, "payment_method": "PIX", "producer": null, "payment_data": { "pix_key": "00020126580014br.gov.bcb.pix0136…6304A1B2", "expiration_date": null, "payment_id": "c1a7e0b2-5d3f-4e8a-9b61-0f2d7c4e9a13", "status": "PENDING", "status_detail": "WAITING_PAYMENT", "total_transaction_value": 99.9 }, "customer": { "name": "João da Silva", "email": "joao@exemplo.com", "document": "12345678909", "phone": "+5511999999999", "birth_date": "15/01/1990", "address": {} } } ``` | Campo | Descrição | | --- | --- | | `event` | Nome do evento que gerou o aviso (tabela acima). | | `transaction_id` | A transação atualizada. Localize o seu pedido por ele. | | `status` | Status da transação no momento do envio. | | `total_value`, `fee`, `net_value` | Valor, taxa e líquido em reais. | | `payment_method` | Em maiúsculas: `PIX`. | | `product`, `producer` | `null` nas cobranças da API; preenchidos nas vendas de produto do checkout da Aruba. | | `payment_data` | O mesmo objeto da [consulta de status](https://docs.arubabr.com/llms/consultar-status.md). | | `customer` | Comprador: `name`, `email`, `document`, `phone`, `birth_date` e `address` (com as chaves `cep`, `street`, `number`, `complement`, `neighborhood`, `city` e `state`; vazio se não foi enviado). | ### Entrega e retentativas - Responda com HTTP `2xx`. Qualquer outro status, ou erro de rede, conta como falha. - São até **3 tentativas** no total, com **15 segundos** entre elas. Depois da terceira falha, aquele aviso não é reenviado: recupere o estado pela consulta de status. - Responda rápido: grave o aviso, devolva `200` e processe em segundo plano. - A ordem de chegada não é garantida. Por isso, confirme o status atual na consulta antes de agir. ### Segurança A Aruba não assina o corpo do aviso. Proteja o seu endpoint com a autenticação do cadastro (Basic Auth ou Bearer Token), que é enviada no header `Authorization` a cada disparo, e confirme sempre o status na consulta. > **Atenção — Confirme sempre na consulta** > > Trate o corpo do webhook como um aviso, não como prova de pagamento. Antes de liberar o pedido, confirme com `GET /api/v1/payments/{transaction_id}/status`. Use HTTPS e confira o header `Authorization` ao receber. ### Idempotência - O mesmo aviso pode chegar mais de uma vez (retentativas e atualizações repetidas). Liberar o pedido duas vezes precisa ser impossível. - Uma transação aprovada pode mudar depois para `REFUNDED`, `CHARGEBACK` ou `IN_DISPUTE`. Não descarte um aviso só porque já viu aquele `transaction_id`: deduplique por `transaction_id` + `status`. - Torne a liberação atômica: marque o pedido como pago numa atualização condicional (por exemplo, `UPDATE … WHERE status <> 'pago'`) e entregue só se a atualização mudou uma linha. ### Exemplo de receptor No cadastro do webhook, escolha *Bearer Token* e informe o valor de `ARUBA_WEBHOOK_TOKEN`. **Node.js** ```javascript import express from "express"; const app = express(); app.use(express.json()); const API = "https://api.arubabr.com/api/v1"; app.post("/webhooks/aruba", async (req, res) => { if (req.get("authorization") !== `Bearer ${process.env.ARUBA_WEBHOOK_TOKEN}`) return res.sendStatus(401); res.sendStatus(200); // responda logo; processe em seguida const transactionId = req.body?.transaction_id; if (!transactionId) return; const pedido = await db.pedidos.porTransacao(transactionId); if (!pedido) return; // transação que não é desta integração // Confirma o status na fonte antes de agir const r = await fetch(`${API}/payments/${transactionId}/status`); if (!r.ok) return; const { data } = await r.json(); if (data.status === "AUTHORIZED") { const mudou = await db.pedidos.marcarPagoSeAindaNao(pedido.id); // UPDATE condicional if (mudou) await liberarPedido(pedido); } else if (["REFUNDED", "CHARGEBACK"].includes(data.status)) { await revogarPedido(pedido); } }); app.listen(3000); ``` **PHP** ```php 'pago' // Se mudou 1 linha, libere o pedido. } ``` --- ## Status da transação O campo `status` da consulta e do webhook diz em que ponto a transação está. A venda está paga só com `AUTHORIZED`. ### Ciclo de vida - `PENDING` → `AUTHORIZED` → `REFUNDED` · `CHARGEBACK` · `IN_DISPUTE` - `PENDING` → `REJECTED` · `CANCELED` ### Tabela de status | Status | Significado | O que fazer | Webhook | | --- | --- | --- | --- | | `PENDING` | Cobrança criada, aguardando o pagamento. | Mostrar os dados de pagamento e aguardar. | sim | | `AUTHORIZED` | **Pago.** | Liberar o pedido, uma única vez. | sim | | `REJECTED` | Recusado. | Oferecer uma nova tentativa (nova cobrança). | sim | | `CANCELED` | Cancelado. | Encerrar o pedido ou gerar nova cobrança. | sim | | `REFUNDED` | Valor devolvido ao comprador. | Revogar acesso ou entrega. | sim | | `CHARGEBACK` | Pagamento contestado pelo comprador. | Revogar acesso ou entrega. | sim | | `IN_DISPUTE` | Disputa aberta, em análise. | Suspender a entrega e acompanhar. | sim | | `FAILED` | O processador não gerou a cobrança. | A criação já respondeu erro; corrija e tente de novo. | não | | `DISPUTE_ACCEPTED` | Disputa encerrada com devolução ao comprador. | Revogar acesso ou entrega. | não | | `DISPUTE_REJECTED` | Disputa encerrada a favor da venda. | A venda segue válida. | não | Os status sem webhook só aparecem na [consulta de status](https://docs.arubabr.com/llms/consultar-status.md) e no painel. > **Atenção — Não existe status de expiração** > > Uma cobrança vencida e não paga pode continuar `PENDING` ou passar para `REJECTED` ou `CANCELED`, conforme o processador. Controle o prazo do pedido do seu lado. > **Nota — AUTHORIZED pode mudar** > > Depois de pago, um pedido ainda pode virar `REFUNDED`, `CHARGEBACK` ou `IN_DISPUTE`. Mantenha o webhook tratando esses status mesmo para pedidos já entregues. --- ## Erros Erros respondem com `hasError: true`, o código HTTP em `statusCode` e a mensagem em `error`. Erros de validação listam cada problema em `errorFields`. ### Formato **400 Bad Request** ```json { "hasError": true, "error": "Erro na validação dos campos", "errorFields": [ "amount must not be less than 1", "customer.email must be an email" ], "statusCode": 400, "timestamp": "2026-10-23T15:19:00.782Z", "path": "/api/v1/direct-payments" } ``` | Campo | Descrição | | --- | --- | | `hasError` | Sempre `true` em erro. | | `error` | Mensagem principal. Nos erros de validação, é `Erro na validação dos campos`. | | `errorFields` | Lista de problemas de validação, cada um citando o campo (ex.: `customer.email`). Vazia nos demais erros. As mensagens padrão de validação vêm em inglês. | | `statusCode` | O mesmo código HTTP da resposta. | | `timestamp`, `path` | Momento (ISO 8601, UTC) e caminho da requisição. Úteis ao falar com o suporte. | ### Códigos HTTP | HTTP | Quando | | --- | --- | | 200 | Consulta de status com sucesso. | | 201 | Cobrança criada. | | 400 | Dados inválidos ou regra de negócio: validação, documento, recusa do processador. Também quando a transação consultada não existe. | | 401 | API Key ausente, inválida ou pausada, ou conta bloqueada. | | 404 | Rota inexistente. Confira o método HTTP e o caminho. | | 429 | Muitas requisições em pouco tempo. Espere alguns segundos e tente de novo. | | 500 | Erro inesperado. Tente de novo; se persistir, fale com o suporte informando `timestamp` e `path`. | ### Mensagens comuns #### Autenticação · 401 Header `X-API-Key` ausente, chave inválida ou inativa, ou conta bloqueada. As mensagens estão em [Autenticação](https://docs.arubabr.com/llms/autenticacao.md). #### Validação · 400, em `errorFields` | Mensagem | Causa | | --- | --- | | `property currency should not exist` | Campo desconhecido no corpo (aqui, `currency`). | | `amount must not be less than 1` | `amount` abaixo do mínimo. | | `customer.email must be an email` | E-mail em formato inválido. | | `document deve ser um CPF/CNPJ válido (somente números)…` | O documento do comprador não é um CPF ou CNPJ válido. | | `A data de nascimento deve ser válida e estar no formato DD/MM/YYYY` | `birthDate` fora do formato. | #### Regras de negócio · 400, em `error` | Mensagem | Causa | | --- | --- | | `document é obrigatório para este método de pagamento` | PIX sem CPF/CNPJ. | | `document deve ser um CPF ou CNPJ válido (somente números)` | PIX com documento inválido. | | `Você ainda não possui documentos validados para gerar pagamentos` | Validação de documentos da conta pendente. | | Mensagem variável | O processador não gerou a cobrança PIX. A transação fica `FAILED`. | | `Pedido não encontrado!` | Consulta de status com `transaction_id` inexistente. | ### Como tratar - **400 de validação ou regra:** corrija a requisição. Repetir igual dá o mesmo erro. - **Recusa do processador:** pode tentar de novo, manualmente. Cada tentativa cria uma nova transação. - **429, 500 e timeouts:** espere e tente de novo com intervalo crescente. Antes de recriar uma cobrança, confira no painel se a anterior não foi criada. --- ## Valores e limites Unidades de valor, mínimo, formatos de dados e limites da conta. ### Unidades de valor | Onde | Unidade | Exemplo | | --- | --- | --- | | `amount` na criação | Inteiro, em centavos de real | `9990` = R$ 99,90 | | `total_value` na resposta da criação | Decimal, em reais | `99.9` | | `total_value`, `fee`, `net_value` na consulta e no webhook | Decimal, em reais | `99.9` | ### Valor mínimo | Método | Mínimo de `amount` | Equivale a | | --- | --- | --- | | `pix` | `1` | R$ 0,01 (limite da validação da API) | ### Tamanho dos campos | Campo | Limite | | --- | --- | | `description` | 3 a 255 caracteres | | `customer.name` | 3 a 128 caracteres | | `customer.utm.*` | até 128 caracteres; `src` até 2048 e `sck` até 256 | | `customer.address.*` | veja [Criar cobrança](https://docs.arubabr.com/llms/criar-cobranca.md) | ### Formatos | Dado | Formato | Exemplo | | --- | --- | --- | | CPF / CNPJ | Só números, 11 ou 14 dígitos, dígitos verificadores válidos | `12345678909` | | Telefone | E.164 | `+5511999999999` | | Data de nascimento | `DD/MM/AAAA` | `15/01/1990` | | CEP | 8 dígitos, sem hífen | `01310100` | | Datas nas respostas | ISO 8601, UTC | `2026-10-23T15:19:00.782Z` | ### Limites da conta - **API Keys:** até 10 ativas por conta. - **Webhooks:** o painel aceita até 10 URLs. - **Requisições:** até 100 chamadas a cada 10 segundos por endereço IP. Acima disso a API responde `429`. Faça polling a cada 5 a 15 segundos, nunca em laço contínuo. --- ## Checklist de produção Confira estes pontos antes de colocar a integração no ar. ### Geral - A API Key fica só no servidor, em variável de ambiente ou cofre de segredos. Nunca no front nem no repositório. - `amount` é inteiro, em centavos de real. - O `transaction_id` é salvo no pedido logo após a criação. - A criação não é repetida automaticamente em erro ou timeout. - O webhook está cadastrado com HTTPS, com os eventos de pagamento e de devolução marcados, e responde `2xx` rápido. - Antes de liberar o pedido, o servidor confirma `AUTHORIZED` na consulta de status, e a liberação é idempotente. - `REFUNDED`, `CHARGEBACK` e `IN_DISPUTE` são tratados também em pedidos já entregues. ### PIX - Copia-e-cola com botão de copiar e QR Code gerado de `pix_key`. - O prazo do pedido é controlado do seu lado; depois dele, uma nova cobrança é gerada. - O polling no navegador (se houver) respeita o intervalo de 5 a 15 segundos e tem limite de tempo.