Jungle Pagamentos
Documentação da API

API de pagamentos PIX

Gere cobranças PIX, acompanhe transações e publique checkouts — com uma única chave de API, respostas previsíveis e liquidação instantânea, rodando na edge.

REST · JSON Auth: X-Api-Key Base: https://app.junglepagamentos.com/api

Introdução

A API é REST, aceita e devolve JSON e vive sob a URL base:

BASEhttps://app.junglepagamentos.com/api

Toda resposta segue o mesmo envelope. Em sucesso, os dados vêm em data; em erro, a mensagem vem em error.

Sucesso
{
  "success": true,
  "data": { ... }
}
Erro
{
  "success": false,
  "error": "Mensagem legível"
}
Valores monetários trafegam em reais (ex.: 49.90), não em centavos. Datas são ISO 8601 em UTC (ex.: 2026-07-21T12:34:56.000Z).

Autenticação

Autentique cada requisição com sua chave de API no header X-Api-Key. Gere/rotacione a chave no painel do seller, em Configurações → API. A chave identifica sua conta e a adquirente ativa; trate-a como segredo.

Header
X-Api-Key: sua_chave_de_api
Requisições sem X-Api-Key retornam 401. Conta inativa/pendente retorna 403. Nunca exponha a chave no front-end.

Para máxima segurança, você pode assinar cada requisição (anti-replay). É opcional e retrocompatível — veja Assinatura anti-replay.

Respostas & erros

Os códigos HTTP seguem a semântica REST:

CódigoSignificado
200OK — leitura bem-sucedida (ou replay idempotente de uma cobrança).
201Created — cobrança/sessão criada.
401Não autenticado — X-Api-Key ausente ou inválida.
403Conta não ativa.
404Recurso não encontrado (ex.: transação inexistente ou de outra conta).
409Conflito de Idempotency-Key — veja Idempotência.
422Payload inválido (validação de campos).
429Rate limit excedido — veja Retry-After.
500Erro interno ou falha da adquirente.

Rate limiting

Os endpoints públicos são limitados por IP em janela fixa. Ao exceder, a API responde 429 com um header Retry-After (segundos). Implemente backoff exponencial e respeite o Retry-After.


POST Criar cobrança PIX

Cria uma transação PIX e devolve o código copia-e-cola para o pagador.

POST/gateway/charges

Corpo da requisição

CampoTipoDescrição
product.name obrigatóriostringNome do produto/pedido.
product.value obrigatórionumberValor em reais (ex.: 49.90).
customer.name obrigatóriostringNome completo do cliente.
customer.email obrigatóriostringE-mail válido.
customer.doc obrigatóriostringCPF ou CNPJ (mín. 11 dígitos).
customer.docType opcional"cpf"|"cnpj"Padrão cpf.
customer.phone opcionalstringTelefone (DDD + número, só dígitos).
customer.zip/street/district/city opcionalstringEndereço de faturamento. customer.number e customer.state não são aceitos por esta rota: se enviados, são descartados silenciosamente (sem erro).
metadata opcionalobjectObjeto livre, devolvido nas consultas.
expiracaoSegundos opcionalnumberValidade do QR em segundos. Padrão 3600.
callbackUrl opcionalstring (URL)URL para receber a notificação de pagamento. Veja Webhooks.
notifyMed opcionalbooleanPadrão false. Com true (e callbackUrl informada), esta cobrança passa a receber também o webhook transaction.med. Veja Webhooks.

Headers

HeaderDescrição
X-Api-Key obrigatórioSua chave de API.
Idempotency-Key opcionalChave única por cobrança para retry seguro. Veja Idempotência.

Exemplo

curl -X POST https://app.junglepagamentos.com/api/gateway/charges \
  -H "X-Api-Key: sua_chave_de_api" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7f3c9a2e-5b1d-4c8a-9e0f-2d6b4a1c8e53" \
  -d '{
    "product": { "name": "Plano Pro", "value": 49.90 },
    "customer": {
      "name": "Ana Souza",
      "email": "ana@exemplo.com",
      "doc": "12345678909",
      "docType": "cpf",
      "phone": "11987654321"
    },
    "expiracaoSegundos": 3600,
    "callbackUrl": "https://sualoja.com/webhooks/pix"
  }'
const res = await fetch("https://app.junglepagamentos.com/api/gateway/charges", {
  method: "POST",
  headers: {
    "X-Api-Key": "sua_chave_de_api",
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(), // opcional; reuse o mesmo valor nos retries
  },
  body: JSON.stringify({
    product: { name: "Plano Pro", value: 49.90 },
    customer: {
      name: "Ana Souza",
      email: "ana@exemplo.com",
      doc: "12345678909",
      docType: "cpf",
      phone: "11987654321",
    },
    expiracaoSegundos: 3600,
  }),
});
const { data } = await res.json();
console.log(data.pixCode);

Resposta 201

200 · application/json
{
  "success": true,
  "data": {
    "transactionId": "a1b2c3d4-e5f6-...",   // use para consultar o status
    "pixCode": "00020101...6304ABCD",      // copia-e-cola / gere o QR
    "expiresAt": "2026-07-21T12:34:56.000Z",
    "amount": 49.90,      // valor bruto (reais)
    "feeAmount": 1.75,    // taxa do gateway
    "netAmount": 48.15     // líquido do seller
  }
}
O pixCode é o BR Code (copia-e-cola). Gere o QR a partir dele no seu front, ou exiba o texto para o cliente colar no app do banco.

Idempotência opcional

Envie o header Idempotency-Key para repetir a criação com segurança (timeout, queda de conexão) sem gerar cobrança duplicada. Sem o header, nada muda.

  • Formato: de 1 a 255 caracteres ASCII visíveis (0x21–0x7E, sem espaço). Um valor fora disso é ignorado — a requisição é tratada como se não tivesse o header, e a resposta (mesmo status e corpo) traz o header Idempotency-Key-Status: ignored. Sem o header na requisição, ele não aparece.
  • Mesmo payload: a ordem das chaves dos objetos JSON não importa; a ordem dos itens de arrays importa.
  • Escopo: a conta (workspace) da chave de API.
  • Validade: permanente — a chave não expira; use um valor novo por cobrança (ex.: UUID).
  • Assinatura: o header fica fora do texto canônico da assinatura. Um retry assinado precisa de X-Nonce e X-Timestamp novos.
RespostaQuando
201Sem chave, ou primeira requisição com a chave — cobrança criada, como sempre.
200Replay: mesma chave e mesmo payload. data idêntico ao do 201 original, com o header Idempotent-Replayed: true. Nenhuma cobrança nova é criada e nenhum webhook é disparado.
409"Idempotency-Key already used with a different payload" — a chave já foi usada com outro corpo.
409"A charge with this Idempotency-Key is still being processed" — a primeira requisição ainda não terminou; aguarde e repita. Se a cobrança seguir sem PIX por mais de 5 minutos, a resposta passa a ser previous_failed (abaixo): use uma chave nova.
409"The charge for this Idempotency-Key failed; retry with a new Idempotency-Key" — a criação original falhou; tente de novo com outra chave.
Header
Idempotency-Key: 7f3c9a2e-5b1d-4c8a-9e0f-2d6b4a1c8e53
A cobrança pode ser consultada por GET /gateway/transactions/:id.

GET Consultar transação

Devolve uma única transação pelo id (o transactionId recebido na criação). É a forma recomendada de polling e de reconciliação — não há janela de 30 dias.

GET/gateway/transactions/:id
curl "https://app.junglepagamentos.com/api/gateway/transactions/a1b2c3d4-e5f6-..." \
  -H "X-Api-Key: sua_chave_de_api"
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-...",
    "status": "PAID",
    // ... mesmos campos de cada item da listagem
    "createdAt": "2026-07-21T11:34:56.000Z",
    "updatedAt": "2026-07-21T12:10:03.000Z"
  }
}
{ "success": false, "error": "Transaction not found" }
data tem exatamente o formato de um item de Listar transações. Transação não encontrada recebe 404.

GET Listar transações

Lista as transações da sua conta com paginação. A ordem é contrato: createdAt decrescente e, no empate, id decrescente. Use este endpoint para reconciliação e sincronização incremental; para uma cobrança específica, prefira GET /gateway/transactions/:id.

GET/gateway/transactions?page=1&limit=20
QueryTipoDescrição
page opcionalnumberPágina, inteiro ≥ 1. Qualquer outro valor vira 1.
limit opcionalnumberItens por página, de 1 a 100. Acima de 100 vira 100; 0, negativo ou não numérico vira 20 (padrão).
status opcionalstringFiltra por PENDING, PAID, FAILED, EXPIRED ou MED (sem diferenciar maiúsculas). Valor inválido é ignorado.
updatedSince opcionalstring (ISO 8601)Só transações com updatedAt ≥ esta data (o mesmo updatedAt devolvido nos itens). Data ilegível é ignorada. Piso de 90 dias: data anterior a agora − 90 dias é tratada como agora − 90 dias (o valor efetivo volta em meta.filters.updatedSince).
Janela padrão: sem updatedSince, a listagem cobre só os últimos 30 dias por createdAt. Com updatedSince, essa janela não se aplica.

O objeto meta traz { total, page, limit, pages }. Quando você envia status ou updatedSince, meta ganha também filters: { status, updatedSince } com os valores aplicados — null indica que o parâmetro foi ignorado por ser inválido.

curl "https://app.junglepagamentos.com/api/gateway/transactions?page=1&limit=20" \
  -H "X-Api-Key: sua_chave_de_api"
{
  "success": true,
  "data": [
    {
      "id": "a1b2c3d4-...",
      "status": "PAID",
      "acquirerId": "zorapay",
      "productName": "Plano Pro",
      "amount": 49.90, "feeAmount": 1.75, "netAmount": 48.15,
      "pixCode": "00020101...6304ABCD",
      "pixExpiresAt": "2026-07-21T12:34:56.000Z",
      "paidAt": "2026-07-21T12:10:03.000Z",
      "customer": { "name": "Ana Souza", "email": "ana@exemplo.com" },
      "metadata": { ... },
      "createdAt": "2026-07-21T11:34:56.000Z",
      "updatedAt": "2026-07-21T12:10:03.000Z"
    }
  ],
  "meta": { "total": 128, "page": 1, "limit": 20, "pages": 7 }
}

Sincronização incremental

  1. Guarde o maior updatedAt que você já viu.
  2. Consulte ?updatedSince= com esse valor menos uma pequena sobreposição (ex.: 1–2 minutos), percorrendo todas as páginas.
  3. Deduplique pelo id e atualize o seu maior updatedAt.
Exemplo
curl "https://app.junglepagamentos.com/api/gateway/transactions?updatedSince=2026-07-21T12:08:00.000Z&status=paid&limit=100" \
  -H "X-Api-Key: sua_chave_de_api"

// meta: { "total": 3, "page": 1, "limit": 100, "pages": 1,
//         "filters": { "status": "PAID", "updatedSince": "2026-07-21T12:08:00.000Z" } }

POST Checkout hospedado

Em vez de gerar o PIX você mesmo, crie uma sessão de checkout e redirecione o cliente para uma página de pagamento hospedada (com seu template, order bumps, etc.). A sessão referencia um checkoutId criado no painel.

POST/checkout/sessions
CampoTipoDescrição
checkoutId obrigatóriostringID do template de checkout (painel).
products obrigatórioarrayItens da compra (nome, valor, quantidade).
customer opcionalobjectDados pré-preenchidos (nome, email, doc, phone).
Resposta · 201
{
  "success": true,
  "data": {
    "sessionId": "8feccd9e-...",
    "amount": 202.40,
    "checkoutUrl": "https://app.junglepagamentos.com/c/8feccd9e-..."
  }
}
Redirecione o cliente para checkoutUrl. Se o checkout tiver domínio próprio configurado, a URL já virá com ele.

Status de pagamento

Toda transação passa por um destes estados:

StatusSignificado
PENDINGCobrança criada, aguardando o pagamento do cliente.
Pagamento confirmado. paidAt preenchido.
FAILEDFalha ao processar / cancelada / estornada.
EXPIREDO QR expirou sem pagamento.
MEDPagamento contestado/devolvido (MED do PIX / chargeback) após ter sido pago.
Recomendado: acompanhe via webhook (tempo real) e use o polling como reconciliação/fallback.

Webhooks

Informe uma callbackUrl ao criar a cobrança para ser notificado quando o status mudar. Anexamos um token à sua URL — valide-o para garantir que a chamada veio da Jungle Pagamentos.

Sua callbackUrl recebe
POST https://sualoja.com/webhooks/pix?token=<token-de-verificacao>
// Responda 2xx para confirmar o recebimento.

Eventos

EventoQuando
transaction.createdCobrança criada.
transaction.paidPagamento confirmado.
transaction.failedFalha / cancelamento.
transaction.expiredPIX expirou sem pagamento.
transaction.med opt-inMED / chargeback: a transação passou a MED. Payload idêntico aos demais transaction.*, com data.status = "MED". Pode chegar mais de uma vez: trate de forma idempotente por transactionId + event. Só é enviado se a cobrança foi criada com notifyMed: true e callbackUrl.
Ignore tipos de evento desconhecidos (responda 2xx e siga em frente): novos eventos podem ser adicionados.

Política de entrega

  • Até 3 tentativas: espera de 0,5 s antes da 2ª e de 2 s antes da 3ª.
  • Timeout de 10 s por tentativa; orçamento total de 15 s por entrega.
  • Nova tentativa só em erro de rede, timeout ou resposta 5xx.
  • 2xx e 4xx são finais — um 4xx não é reenviado.
  • 3xx: seguimos 1 redirecionamento, desde que para um host público; caso contrário é final.
Não há reentrega automática posterior. Se o seu endpoint ficou fora do ar, reconcilie por GET /gateway/transactions/:id ou por ?updatedSince. E não confie apenas no webhook para liberar o produto: confirme o status consultando a transação antes de entregar.

Assinatura anti-replay opcional

Para blindar contra replay, assine a requisição. Se você enviar X-Signature, exigimos também X-Timestamp e X-Nonce. Clientes que não assinam continuam funcionando normalmente.

HeaderDescrição
X-TimestampEpoch em ms. Aceito dentro de ±5 min do horário do servidor.
X-NonceValor único por requisição (evita reuso).
X-SignatureHMAC-SHA256 (hex) do texto canônico, usando a chave de API crua como segredo.
Texto canônico (HMAC)
{METHOD}\n{path}\n{body}\n{X-Timestamp}\n{X-Nonce}

# ex.:  POST\n/api/gateway/charges\n{"product":...}\n1737460000000\nabc123
O header Idempotency-Key não entra no texto canônico. Ao repetir uma requisição assinada, gere X-Timestamp e X-Nonce novos (e a assinatura correspondente).
Sem assinatura, a API opera só com X-Api-Key (padrão). A assinatura é uma camada extra recomendada para integrações server-to-server sensíveis.

Boas práticas

  • Valores em reais. Envie value como 49.90, não em centavos.
  • Guarde o transactionId. É a chave para conciliar o pagamento.
  • Use Idempotency-Key nos retries. Repetir a criação com a mesma chave (e o mesmo corpo) não duplica a cobrança.
  • Não libere só pelo webhook. Confirme o status antes de entregar.
  • Dados do cliente reais. CPF válido, nome completo e telefone (DDD + número) evitam recusa da adquirente.
  • Respeite o 429. Faça backoff e honre o Retry-After.
  • Proteja a chave. Só no back-end; rotacione se vazar.

© Jungle Pagamentos — Documentação da API · PIX na edge da Cloudflare.