Começar
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.
Vai integrar com um assistente de código (Claude, ChatGPT, Cursor, Copilot…)? Passe para ele 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. Veja Para IA.
Como funciona
POST /api/v1/direct-payments com valor, método e comprador, autenticado pela API Key.payment_data: o código PIX copia-e-cola e o QR Code.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
Copia-e-cola e QR Code no app do banco. paymentMethod: "pix"
Webhooks
Avisos de pagamento, estorno, disputa e outros eventos, enviados ao seu servidor.
Endereço da API
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 | Header X-API-Key | Criar uma cobrança |
| GET | /api/v1/payments/{transaction_id}/status | 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).
{
"hasError": false,
"data": { "transaction_id": "7KQ2M9XA4T1B", "status": "PENDING" }
}
{
"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. - 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.
Começar
Início rápido
Sua primeira cobrança PIX em quatro passos. Esse é o fluxo inteiro de uma integração.
-
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 exemploARUBA_API_KEY. -
Crie a cobrança
Chame o endpoint de cobrança a partir do seu servidor.
amountvai em centavos:9990= R$ 99,90.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" } }'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.$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{ "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 } } } -
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. -
Confirme o pagamento
Cadastre a URL do seu servidor em Integração → Webhooks. Quando o PIX for pago, a Aruba envia um
POSTcom"status": "AUTHORIZED". Confirme na consulta de status e libere o pedido.curl https://api.arubabr.com/api/v1/payments/7KQ2M9XA4T1B/status
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
Começar
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
- No painel da Aruba, abra Integração → API Keys.
- Clique em Nova API Key, dê um nome (3 a 100 caracteres) e, se quiser, uma descrição (até 255).
- 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
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 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. |
Cobranças
Criar cobrança
X-API-KeyCria 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). |
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 -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" }
}
}'
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("; ")}`);
$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. |
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. |
| 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.
Cobranças
PIX
Cobrança em reais paga com copia-e-cola ou QR Code no app do banco.
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 -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" }
}'
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 };
$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).
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
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.
Depois do pagamento
Consultar status
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 https://api.arubabr.com/api/v1/payments/7KQ2M9XA4T1B/status
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"…
$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
{
"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. |
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. |
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 e confirme com esta consulta.
Depois do pagamento
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
- No painel da Aruba, abra Integração → Webhooks e clique em Novo Webhook.
- Informe um nome e a URL de destino. Use HTTPS.
- Escolha os eventos que esse webhook deve receber (veja a tabela abaixo). É preciso marcar ao menos um.
- 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.
- 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_idque 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. |
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:
{
"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. |
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
200e 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.
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,CHARGEBACKouIN_DISPUTE. Não descarte um aviso só porque já viu aqueletransaction_id: deduplique portransaction_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.
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
// Bearer Token cadastrado no webhook = ARUBA_WEBHOOK_TOKEN
// Em alguns servidores o header precisa ser repassado ao PHP (ex.: Apache com CGI).
$auth = $_SERVER["HTTP_AUTHORIZATION"] ?? "";
if (!hash_equals("Bearer " . getenv("ARUBA_WEBHOOK_TOKEN"), $auth)) {
http_response_code(401);
exit;
}
$aviso = json_decode(file_get_contents("php://input"), true);
http_response_code(200);
$transactionId = $aviso["transaction_id"] ?? null;
if (!$transactionId) exit;
// Confirma o status na fonte antes de agir
$ch = curl_init("https://api.arubabr.com/api/v1/payments/" . urlencode($transactionId) . "/status");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$status = json_decode(curl_exec($ch), true)["data"]["status"] ?? null;
curl_close($ch);
if ($status === "AUTHORIZED") {
// UPDATE pedidos SET status = 'pago' WHERE transaction_id = ? AND status <> 'pago'
// Se mudou 1 linha, libere o pedido.
}
Depois do pagamento
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
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 e no painel.
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.
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.
Referência
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
{
"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.
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.
Referência
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 |
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.
Referência
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
2xxrápido. - Antes de liberar o pedido, o servidor confirma
AUTHORIZEDna consulta de status, e a liberação é idempotente. REFUNDED,CHARGEBACKeIN_DISPUTEsã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.
Referência
Para IA (llms.txt)
Esta documentação também existe em Markdown, para assistentes de código (Claude, ChatGPT, Cursor, Copilot…) implementarem a integração com as mesmas regras que você leu aqui.
Arquivos
| Arquivo | Conteúdo | Quando usar |
|---|---|---|
/llms-full.txt | A documentação inteira num arquivo só, em Markdown, com as regras para assistentes no início. | Para colar no chat ou passar a URL ao assistente. É o recomendado. |
/llms.txt | Índice no padrão llmstxt.org, com um link por página. | Para ferramentas que leem llms.txt e buscam só as páginas necessárias. |
/llms/<página>.md | Cada página desta documentação em Markdown (ex.: /llms/webhooks.md). | Para dar ao assistente só o trecho de um assunto. |
Prompt sugerido
Leia https://docs.arubabr.com/llms-full.txt inteiro antes de escrever código.
Implemente a integração de pagamentos da Aruba no meu projeto seguindo essa documentação:
- criação da cobrança PIX no servidor com a API Key em variável de ambiente;
- tela de pagamento com o copia-e-cola e o QR Code gerado a partir de pix_key;
- webhook + consulta de status para liberar o pedido só com AUTHORIZED, de forma idempotente.
Respeite todas as regras da seção "Regras para assistentes de código".
Os arquivos são gerados a partir desta página. Se algo mudar aqui, eles mudam junto.