HubPix API
API REST para receber via PIX (cobrança ou QR estático reutilizável), 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 e ative o autenticador (2FA). Todo cadastro passa por aprovação manual da nossa equipe — se você recebeu um código de cupom, informe no cadastro e a conta é liberada na hora. Enquanto não é aprovada, a API responde 403 ACCOUNT_PENDING. Depois de aprovado, 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 |
| Para IA / automação | /openapi.json (OpenAPI 3.1), /llms.txt (índice) e /llms-full.txt (esta documentação inteira em Markdown) |
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 | PIX_IN_DISABLED |
Depósitos (cobranças e QR estático) temporariamente indisponíveis. Saques seguem normais. features.pixIn em GET /v1/account mostra o estado |
| 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": "5.00", "pixInMax": "5000.00", "pixOutMin": "10.00", "pixOutMax": null },
"features": { "pixIn": true, "staticQr": 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". Limites por cobrança: mínimo R$ 5,00 e máximo R$ 5.000,00 (veja limits em GET /v1/account) |
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 } }
QR estático
Um QR estático é um QR fixo e reutilizável: não expira e pode ser pago quantas vezes for preciso. Use para dar um QR próprio a cada vendedor, cliente, máquina ou ponto de venda. Se você é um gateway, use-o para oferecer QR estático aos seus próprios clientes. A cobrança (POST /v1/pix/charges) é diferente: é dinâmica, vale para um pagamento só e expira.
Cada pagamento recebido vira uma transação PIX_IN própria, com origin: "STATIC_QR" e staticQr: { id, reference }. Ela já nasce PAID, com o líquido no seu saldo, e dispara o webhook pix_in.paid. A taxa é a mesma do PIX In.
GET /v1/account mostra em features.staticQr se o recurso está habilitado na sua conta. Se não estiver, a criação responde 403 FEATURE_DISABLED.
POST /v1/pix/static-qrs
| Campo | Descrição | |
|---|---|---|
reference |
recomendado | Seu identificador do QR (id do vendedor/cliente), até 64 caracteres: letras, números e . _ : -. É único na sua conta e serve de idempotência: criar de novo a mesma reference com os mesmos dados devolve o mesmo QR (200), sem duplicar. Se for omitido, geramos um |
amount |
opcional | Sem amount, o valor é aberto e o pagador digita. Com amount ("25.00"), o QR tem valor fixo, dentro dos limites de PIX In da conta |
merchantName |
opcional | Nome mostrado ao pagador no app do banco, até 25 caracteres. Convertemos para maiúsculas e tiramos os acentos |
merchantCity |
opcional | Cidade do recebedor, até 15 caracteres |
description |
opcional | Até 140 caracteres. Vai em cada pagamento recebido |
curl -X POST https://hubpixtech.com/v1/pix/static-qrs \
-H "X-API-Key: hpx_pk_SUA_CHAVE" \
-H "Content-Type: application/json" \
-d '{ "reference": "vendedor-001", "merchantName": "LOJA DO JOAO", "merchantCity": "SAO PAULO" }'
Resposta 201:
{
"success": true,
"data": {
"id": "0b6c7e1a-3d2f-4c9e-8a1b-5f6e7d8c9b0a",
"reference": "vendedor-001",
"status": "ACTIVE",
"amount": null,
"merchantName": "LOJA DO JOAO",
"merchantCity": "SAO PAULO",
"description": null,
"qrCode": "00020101021126580014br.gov.bcb.pix...",
"paymentsCount": 0,
"totalReceived": "0.00",
"lastPaidAt": null,
"failureReason": null,
"createdAt": "2026-10-02T12:00:00.000Z",
"updatedAt": "2026-10-02T12:00:00.000Z"
}
}
Se você repetir a mesma reference com outro amount, merchantName ou merchantCity, a resposta é 409 REFERENCE_CONFLICT. Um QR não muda depois de criado: para outro valor fixo, crie outra reference.
Guarde o
ide areference, não oqrCode. O copia e cola pode ser regenerado por manutenção, então busque-o de novo quando for exibir. O QR continua o mesmo e os pagamentos continuam caindo nele. Oriente o pagador a escanear o QR ou usar o copia e cola: um PIX feito digitando uma chave não é vinculado ao QR.
GET /v1/pix/static-qrs/{id}
Devolve o QR com o qrCode atual e os totais recebidos (paymentsCount, totalReceived, lastPaidAt). Para buscar pela sua reference, use GET /v1/pix/static-qrs?reference=vendedor-001.
Parâmetros opcionais de query geram um código pontual do mesmo QR, sem alterar o que foi salvo: amount (valor daquela vez), merchantName e merchantCity. O pagamento cai no mesmo QR e é identificado normalmente. Exemplo: GET /v1/pix/static-qrs/{id}?amount=25.00. Esse uso tem limite de 6 por minuto por QR.
GET /v1/pix/static-qrs
Lista paginada dos seus QRs. Query: status (ACTIVE | FAILED), search (trecho da reference), page e limit (máximo 100). Na listagem o qrCode é o último salvo. Para exibir ao pagador, consulte o QR pelo id.
GET /v1/pix/static-qrs/{id}/payments
Pagamentos recebidos naquele QR, do mais recente para o mais antigo, no mesmo formato de transação (PIX_IN). Query: page e limit. Os pagamentos também aparecem em GET /v1/transactions e em GET /v1/pix/charges, com origin: "STATIC_QR".
Como na cobrança, um pagamento só entra no saldo depois de confirmado na liquidação, normalmente alguns segundos após o PIX. Num QR de valor aberto, um pagamento abaixo do mínimo de PIX In é creditado mesmo assim, mas a taxa é no mínimo o custo do recebimento.
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 ou pagamento de QR estático confirmado. O valor líquido já está no seu saldo. No QR estático, o evento traz origin: "STATIC_QR" e staticQr |
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:
/openapi.json: especificação OpenAPI 3.1 com todos os endpoints, campos e erros. Importe no seu agente, no Postman ou num gerador de SDK./llms.txt: índice no padrão llms.txt, com as seções e a lista de endpoints./llms-full.txt: esta documentação inteira em Markdown puro, para colocar no contexto do modelo.- Respostas sempre no mesmo envelope (
success,dataouerror.code) e códigos de erro estáveis, fáceis de tratar automaticamente. Idempotency-Keytorna seguro repetir chamadas: um agente que repete umPOSTnão duplica cobrança nem saque.
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
- Confirme pedidos pelo webhook
pix_in.paid. Na dúvida, consulteGET /v1/pix/charges/{id}, sem polling agressivo. - Gere uma
Idempotency-Keypor operação e reutilize a mesma ao repetir uma chamada que falhou por rede. - Trate
UNDER_REVIEWcomo "aguardando". O dinheiro não sumiu: está reservado até a análise terminar. - Guarde
X-Secret-Keysó no servidor que faz saques e mantenha na whitelist de saque apenas os IPs dele. - Use uma chave por sistema. Se uma vazar, revogue só ela.
Atualizado em 02/10/2026, 21:11 (horário de Brasília).