HubPix API

API REST para receber e pagar via PIX e sacar em USDT (BSC), com webhooks assinados e gerenciáveis pela própria API. Tudo o que o painel faz com dinheiro e integração também pode ser feito por aqui, inclusive por agentes de IA.

Começando: crie a conta em hubpixtech.com/cadastro, ative o autenticador (2FA), gere sua chave em API e segurança e cadastre o IP do seu servidor na whitelist de saque.

Base URL https://hubpixtech.com/v1
Formato JSON. Sucesso: { "success": true, "data": ... }. Erro: { "success": false, "error": { "code", "message" } }
Valores Sempre string decimal com ponto, em reais: "100.00"
Datas ISO 8601 em UTC: 2026-10-02T12:00:00.000Z
OpenAPI /openapi.json (OpenAPI 3.1), e esta documentação em Markdown em /llms.txt

Autenticação

As chaves são geradas no painel, em API e segurança → Nova chave (pede o código do autenticador). Cada chave é um par: a pública e o segredo de saque. Elas são exibidas uma única vez: guarde em local seguro e nunca as coloque no frontend. Você pode ter até 5 chaves ativas (por exemplo, uma por sistema) e revogar qualquer uma a qualquer momento.

Header Credencial Onde é exigida
X-API-Key hpx_pk_... Todas as requisições
X-Secret-Key hpx_sk_... Saques e ações sensíveis (POST /v1/pix/withdrawals, POST /v1/usdt/withdrawals, PUT /v1/ip-allowlist, DELETE /v1/api-keys/{id})

O X-Secret-Key precisa ser o do mesmo par da X-API-Key usada na requisição.

Whitelist de IP

São duas listas, ambas editáveis no painel (com 2FA). Cada lista aceita até 20 entradas, com IP único (203.0.113.10) ou faixa CIDR (203.0.113.0/24, até /16 no IPv4 e /48 no IPv6).

Lista Efeito
Saque Obrigatória para sacar pela API. Só esses IPs podem chamar os endpoints que exigem X-Secret-Key. Sem nenhum IP cadastrado, o saque pela API é recusado com 403 IP_NOT_ALLOWED, e a mensagem traz o IP que chegou até nós
API Opcional. Se tiver algum IP, todas as chamadas da API (inclusive consultas) passam a ser aceitas só desses IPs. Vazia: qualquer IP

A primeira lista de saque é cadastrada pelo painel. Depois disso você também pode trocá-la pela API (PUT /v1/ip-allowlist), mas só a partir de um IP que já esteja nela. Assim, uma chave vazada não consegue liberar o IP de quem a roubou. Para descobrir o IP que o seu servidor usa para chegar até nós, chame GET /v1/account dele e veja requestIp.

Idempotência

Envie o header Idempotency-Key (um UUID gerado por você, de 8 a 100 caracteres) em todo POST que cria cobrança ou saque. Se a rede cair e você repetir a chamada com a mesma chave, a operação não é duplicada: devolvemos a mesma transação, com HTTP 200 em vez de 201.

Idempotency-Key: 9f3c2a1e-7b4d-4f1a-9c3e-2d5b8a7f6e01

O externalRef também é único por tipo de operação: repetir um externalRef já usado devolve 409 DUPLICATE.

Erros

HTTP code Quando
400 INVALID_JSON / BAD_REQUEST Corpo mal formado
401 INVALID_KEY X-API-Key ausente, inválida ou revogada
401 INVALID_SECRET X-Secret-Key ausente ou inválida em um saque
403 ACCOUNT_BLOCKED Conta bloqueada
403 ACCOUNT_PENDING Conta aguardando aprovação
403 SCOPE_DENIED Operação não habilitada para sua conta
403 IP_NOT_ALLOWED IP fora da whitelist (de saque ou da API)
404 NOT_FOUND Recurso inexistente ou de outra conta
409 DUPLICATE externalRef ou Idempotency-Key já usados
422 VALIDATION_ERROR Campo inválido (detalhe em message)
422 AMOUNT_OUT_OF_RANGE Valor fora dos limites da sua conta
422 INSUFFICIENT_BALANCE Saldo insuficiente para o saque
429 RATE_LIMITED Limite de requisições excedido
502 CHARGE_UNAVAILABLE Não foi possível gerar a cobrança agora; tente de novo
503 QUOTE_UNAVAILABLE Cotação de USDT indisponível no momento

Limites de requisição

Até 600 requisições por minuto por conta. Acima disso a resposta é 429 RATE_LIMITED. Para acompanhar o status de uma transação, use webhooks. Se precisar consultar, faça no máximo 1 consulta por minuto por transação.

Conta e saldo

GET /v1/account

Dados da conta: status, saldo, suas taxas (fees), limites por operação, recursos habilitados e requestIp (o IP de onde a chamada chegou).

{
  "success": true,
  "data": {
    "id": "c802502e-...", "name": "Minha Loja", "email": "[email protected]", "status": "ACTIVE",
    "balance": "1520.40", "heldBalance": "250.00",
    "fees": { "pixIn": { "percent": "7", "fixed": "0.00", "minimum": "0.00" }, "pixOut": { "percent": "0", "fixed": "0.00" }, "usdt": { "spreadPercent": "0" } },
    "limits": { "pixInMin": "10.00", "pixInMax": null, "pixOutMin": "1.00", "pixOutMax": null },
    "features": { "pixIn": true, "pixOut": true, "usdtOut": true, "usdtNetworks": ["BEP20"] },
    "requestIp": "203.0.113.10"
  }
}

A taxa do PIX In é max(mínimo, valor × percent% + fixo). A taxa do saque PIX é valor × percent% + fixo, somada por fora.

GET /v1/balance

curl https://hubpixtech.com/v1/balance -H "X-API-Key: hpx_pk_SUA_CHAVE"
{ "success": true, "data": { "balance": "1520.40", "heldBalance": "250.00" } }

balance é o que está disponível para saque. heldBalance é o que está reservado em saques ainda em andamento.

PIX In (cobranças)

POST /v1/pix/charges

Cria uma cobrança PIX e devolve o copia e cola (qrCode), que você mostra ao pagador como texto ou QR Code.

Campo Descrição
amount obrigatório Valor bruto, string: "100.00"
externalRef opcional Seu identificador (id do pedido), até 100 caracteres. Volta nos webhooks e permite consulta
description opcional Até 140 caracteres
expiresIn opcional Segundos até expirar, de 60 a 1800. Padrão: 1800 (30 min)
curl -X POST https://hubpixtech.com/v1/pix/charges \
  -H "X-API-Key: hpx_pk_SUA_CHAVE" \
  -H "Idempotency-Key: 9f3c2a1e-7b4d-4f1a-9c3e-2d5b8a7f6e01" \
  -H "Content-Type: application/json" \
  -d '{ "amount": "100.00", "externalRef": "pedido-1042", "description": "Pedido #1042" }'

Resposta 201:

{
  "success": true,
  "data": {
    "id": "6f1d2c3b-9a8e-4f7d-b6c5-1a2b3c4d5e6f",
    "type": "PIX_IN",
    "status": "PENDING",
    "amount": "100.00",
    "fee": "7.00",
    "netAmount": "93.00",
    "externalRef": "pedido-1042",
    "description": "Pedido #1042",
    "qrCode": "00020126580014br.gov.bcb.pix...",
    "expiresAt": "2026-10-02T12:30:00.000Z",
    "paidAt": null,
    "endToEndId": null,
    "payer": null,
    "createdAt": "2026-10-02T12:00:00.000Z",
    "updatedAt": "2026-10-02T12:00:00.000Z"
  }
}

netAmount é o que entra no seu saldo depois da taxa.

GET /v1/pix/charges/{id}

Consulta uma cobrança pelo id. Para consultar pelo seu identificador, use GET /v1/pix/charges?externalRef=pedido-1042.

Status: PENDING → PAID | EXPIRED | CANCELLED. Uma cobrança que não pôde ser gerada fica FAILED.

Quando PAID, a resposta traz paidAt, endToEndId e payer (name, document, institution, quando disponíveis).

O pagamento só é marcado como PAID, e o saldo só é creditado, depois de confirmado na liquidação. Por isso o status muda alguns segundos depois do pagamento, nunca antes.

GET /v1/pix/charges

Lista paginada. Query: status, from, to (ISO 8601), page (padrão 1) e limit (padrão 50, máximo 100).

{ "success": true, "data": { "items": [ ... ], "page": 1, "limit": 50, "total": 132 } }

PIX Out (saques)

POST /v1/pix/withdrawals

Envia um PIX a partir do seu saldo. Exige X-API-Key, X-Secret-Key e o IP na whitelist de saque.

amount é o valor que chega ao recebedor. A taxa é somada por fora, e o total (totalAmount) sai do seu saldo no momento do pedido.

Campo Descrição
amount obrigatório Valor que o recebedor recebe, string
pixKey + pixKeyType opção A pixKeyType: CPF, CNPJ, EMAIL, PHONE ou EVP (chave aleatória)
brCode opção B Código PIX copia e cola do recebedor
externalRef opcional Seu identificador. Volta nos webhooks
description opcional Até 140 caracteres
curl -X POST https://hubpixtech.com/v1/pix/withdrawals \
  -H "X-API-Key: hpx_pk_SUA_CHAVE" \
  -H "X-Secret-Key: hpx_sk_SEU_SECRET" \
  -H "Idempotency-Key: 41d1f2ab-90c7-4e2b-b7d3-0f6a8c9d1e22" \
  -H "Content-Type: application/json" \
  -d '{ "amount": "250.00", "pixKey": "12345678900", "pixKeyType": "CPF", "externalRef": "repasse-778" }'

Resposta 201:

{
  "success": true,
  "data": {
    "id": "0b7e6f2a-3c4d-4e5f-8a9b-0c1d2e3f4a5b",
    "type": "PIX_OUT",
    "status": "PROCESSING",
    "amount": "250.00",
    "fee": "3.00",
    "totalAmount": "253.00",
    "pixKey": "12345678900",
    "pixKeyType": "CPF",
    "externalRef": "repasse-778",
    "endToEndId": null,
    "failureReason": null,
    "createdAt": "2026-10-02T12:05:00.000Z"
  }
}

Formato da chave: CPF e CNPJ só com dígitos (pontuação é removida). Telefone com DDD; aceitamos 11999998888, 5511999998888 ou +5511999998888.

Status do saque

Status Significado Saldo
PROCESSING Pagamento enviado, aguardando liquidação totalAmount reservado
COMPLETED Pago. endToEndId é o comprovante debitado
FAILED Não foi pago. Motivo em failureReason devolvido ao saldo
UNDER_REVIEW Resultado não confirmado; em análise manual pela nossa equipe continua reservado

Cada saque é enviado uma única vez. Nunca reenviamos um pagamento automaticamente. Quando o resultado não pode ser confirmado com segurança, o saque vai para UNDER_REVIEW e o valor fica reservado até a nossa equipe concluir a análise. Ao final, ele vira COMPLETED ou FAILED, e você recebe o webhook correspondente. Não crie outro saque para o mesmo pagamento enquanto ele estiver em análise.

GET /v1/pix/withdrawals/{id}

Consulta pelo id, ou por GET /v1/pix/withdrawals?externalRef=.... GET /v1/pix/withdrawals lista os saques, com os mesmos filtros da listagem de cobranças.

Saque em USDT

Saque do seu saldo em reais convertido para USDT, enviado para uma carteira sua na BNB Smart Chain (BEP20). É a única rede aceita: o campo network pode ser omitido ou enviado como "BEP20".

GET /v1/usdt/quote

Simula o saque. Informe network e um destes: amountUsdt (quanto você quer receber) ou amountBrl (quanto quer gastar, já com a taxa de rede).

curl "https://hubpixtech.com/v1/usdt/quote?amountUsdt=100" -H "X-API-Key: hpx_pk_SUA_CHAVE"
{
  "success": true,
  "data": {
    "network": "BEP20",
    "rate": "5.4210",
    "amountUsdt": "100.00",
    "networkFeeUsdt": "1.00",
    "amountBrl": "542.10",
    "feeBrl": "5.43",
    "totalBrl": "547.53",
    "validForSeconds": 30,
    "networks": ["BEP20"]
  }
}

A cotação é indicativa. O valor final é calculado no momento do POST.

POST /v1/usdt/withdrawals

Exige X-API-Key, X-Secret-Key e o IP na whitelist de saque.

Campo Descrição
network opcional BEP20 (única rede; é o padrão)
address obrigatório Endereço 0x... (40 hex) da sua carteira na BNB Smart Chain
amountUsdt ou amountBrl obrigatório Um dos dois, como na cotação
externalRef, description opcional Como nos outros saques
curl -X POST https://hubpixtech.com/v1/usdt/withdrawals \
  -H "X-API-Key: hpx_pk_SUA_CHAVE" -H "X-Secret-Key: hpx_sk_SEU_SECRET" \
  -H "Idempotency-Key: 7a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d" \
  -H "Content-Type: application/json" \
  -d '{ "address": "0x9f8e7d6c5b4a39281706f5e4d3c2b1a098765432", "amountUsdt": "100.00", "externalRef": "cripto-55" }'

O total em reais (totalAmount) é debitado na hora e o pedido nasce com status REQUESTED. Depois do envio na blockchain, ele vira COMPLETED com usdt.txHash (consulte em https://bscscan.com/tx/<txHash>). Se não puder ser enviado, vira FAILED e o valor volta ao seu saldo. Confira o endereço e a rede: USDT enviado para endereço ou rede errados não tem como ser recuperado.

GET /v1/usdt/withdrawals/{id} consulta o pedido. GET /v1/usdt/withdrawals lista os pedidos.

Extrato

GET /v1/transactions

Todas as suas transações. Filtros: type (PIX_IN, PIX_OUT, USDT_OUT), status, externalRef, from, to, page e limit. GET /v1/transactions/{id} consulta uma transação de qualquer tipo.

Webhooks

Você cadastra, edita e remove as URLs que recebem os eventos pela própria API (ou pelo painel). Pode ter até 10 URLs, cada uma com sua lista de eventos e seu próprio segredo de assinatura. GET /v1/webhooks/events lista os eventos disponíveis.

Eventos

Evento Quando dispara
pix_in.paid Cobrança paga e confirmada. O valor líquido já está no seu saldo
pix_in.expired Cobrança expirou ou foi cancelada sem pagamento
pix_out.completed Saque PIX pago (com endToEndId)
pix_out.failed Saque PIX não foi pago. O valor voltou ao seu saldo
pix_out.under_review Saque PIX entrou em análise manual. O valor segue reservado
usdt_out.completed Saque USDT enviado (com usdt.txHash)
usdt_out.failed Saque USDT cancelado. O valor voltou ao seu saldo
webhook.test Disparo de teste feito por você

Use "*" para assinar todos os eventos.

POST /v1/webhooks: cadastrar

Campo Descrição
url obrigatório URL HTTPS pública
events opcional Lista de eventos. Padrão: ["*"]
description opcional Rótulo livre
active opcional Padrão true
curl -X POST https://hubpixtech.com/v1/webhooks \
  -H "X-API-Key: hpx_pk_SUA_CHAVE" -H "Content-Type: application/json" \
  -d '{ "url": "https://seusite.com.br/webhooks/hubpix", "events": ["pix_in.paid", "pix_out.completed", "pix_out.failed"] }'
{
  "success": true,
  "data": {
    "id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
    "url": "https://seusite.com.br/webhooks/hubpix",
    "events": ["pix_in.paid", "pix_out.completed", "pix_out.failed"],
    "description": null,
    "active": true,
    "secret": "whsec_3f9a...",
    "createdAt": "2026-10-02T12:00:00.000Z"
  }
}

O secret aparece só nesta resposta e na rotação. Guarde-o para validar a assinatura.

Demais operações

Método e rota O que faz
GET /v1/webhooks Lista suas URLs
GET /v1/webhooks/{id} Detalhe de uma URL
PATCH /v1/webhooks/{id} Altera url, events, description ou active (envie só o que muda)
DELETE /v1/webhooks/{id} Remove a URL. Entregas pendentes para ela são canceladas
POST /v1/webhooks/{id}/rotate-secret Gera um segredo novo. O anterior para de valer na hora
POST /v1/webhooks/{id}/test Envia um webhook.test agora e devolve o resultado da entrega
GET /v1/webhooks/{id}/deliveries Últimas entregas: status, tentativas, último HTTP e erro
POST /v1/webhooks/{id}/deliveries/{deliveryId}/redeliver Reenvia uma entrega

Formato da entrega

POST https://seusite.com.br/webhooks/hubpix
Content-Type: application/json
X-HubPix-Event: pix_in.paid
X-HubPix-Delivery: evt_5c1a9e0b7f3d2a4e6b8c0d1f
X-HubPix-Signature: t=1791000000,v1=6a1c9d...
{
  "id": "evt_5c1a9e0b7f3d2a4e6b8c0d1f",
  "event": "pix_in.paid",
  "createdAt": "2026-10-02T12:03:12.000Z",
  "data": {
    "transaction": {
      "id": "6f1d2c3b-9a8e-4f7d-b6c5-1a2b3c4d5e6f",
      "type": "PIX_IN",
      "status": "PAID",
      "amount": "100.00",
      "fee": "7.00",
      "netAmount": "93.00",
      "externalRef": "pedido-1042",
      "paidAt": "2026-10-02T12:03:10.000Z",
      "endToEndId": "E1234567820261002...",
      "payer": { "name": "Maria Souza", "document": "12345678900", "institution": "BANCO X" }
    }
  }
}

data.transaction tem o mesmo formato da consulta da transação. Responda com qualquer 2xx em até 10 segundos. Processe de forma assíncrona se precisar de mais tempo.

O mesmo evento pode chegar mais de uma vez (reentrega). Use X-HubPix-Delivery (igual ao id do corpo) para processar cada evento uma vez só.

Verificar a assinatura

O header X-HubPix-Signature tem o formato t=<unix>,v1=<hex>, onde:

v1 = HMAC_SHA256(secret, t + "." + corpoBruto)

Rejeite entregas com assinatura inválida ou com t a mais de 5 minutos do seu relógio.

const crypto = require('node:crypto');
function verificaHubPix(rawBody, header, secret) {
  const t  = (header.match(/t=(\d+)/) || [])[1];
  const v1 = (header.match(/v1=([a-f0-9]+)/) || [])[1];
  if (!t || !v1) return false;
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const esperado = crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex');
  return v1.length === esperado.length && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(esperado));
}
function verificaHubPix(string $rawBody, string $header, string $secret): bool {
    preg_match('/t=(\d+)/', $header, $t); preg_match('/v1=([a-f0-9]+)/', $header, $v);
    if (!$t || !$v || abs(time() - (int)$t[1]) > 300) return false;
    return hash_equals(hash_hmac('sha256', $t[1] . '.' . $rawBody, $secret), $v[1]);
}

Use o corpo bruto da requisição, exatamente como chegou, e não o JSON já convertido.

Reentregas

Se a sua URL não responder 2xx em 10 segundos, reenviamos com intervalos crescentes: 1 min, 5 min, 15 min, 1 h, 6 h e 24 h (7 tentativas no total). Depois disso a entrega fica como FAILED e você pode reenviá-la por POST /v1/webhooks/{id}/deliveries/{deliveryId}/redeliver.

Mesmo sem webhook, você sempre pode conferir pela consulta da transação ou pelo extrato.

Chaves e whitelist pela API

Método e rota Credencial O que faz
GET /v1/api-keys X-API-Key Lista suas chaves (nome, final, último uso e IP). current: true marca a chave usada na chamada
DELETE /v1/api-keys/{id} + X-Secret-Key, IP da whitelist de saque Revoga uma chave na hora
GET /v1/ip-allowlist X-API-Key Mostra as duas listas e o requestIp
PUT /v1/ip-allowlist + X-Secret-Key, IP da whitelist de saque Substitui api e/ou withdraw. A nova lista de saque precisa continuar contendo o IP da requisição

Criar chave nova só é possível pelo painel, porque exige o código do autenticador.

curl -X PUT https://hubpixtech.com/v1/ip-allowlist \
  -H "X-API-Key: hpx_pk_SUA_CHAVE" -H "X-Secret-Key: hpx_sk_SEU_SECRET" -H "Content-Type: application/json" \
  -d '{ "withdraw": ["203.0.113.10", "198.51.100.0/24"], "api": [] }'

Integração com IA e automação

A API foi feita para ser operada por código e por agentes de IA, do mesmo jeito que pelo painel:

Recomendação de segurança para agentes: dê ao agente uma chave própria (crie uma só para ele) e rode-o num servidor cujo IP esteja na whitelist. Se o agente não deve sacar, não entregue o X-Secret-Key a ele: só com a X-API-Key ele cria cobranças, consulta e gerencia webhooks, mas não move dinheiro para fora.

Boas práticas