SDK PHP
Um arquivo, sem dependências. createInvoice(), getInvoice() e verifyWebhook() — insira em qualquer projeto.
Um único SDK PHP sem dependências: crie faturas, redirecione para o checkout hospedado e verifique webhooks assinados. REST está disponível para qualquer linguagem.
api.payora.moneyUma chamada de API com um ID de pedido e um valor em fiat ou cripto retorna uma URL de pagamento hospedada.
Eles escolhem uma moeda, escaneiam o QR ou abrem uma carteira, e o checkout confirma ao vivo na finalização.
Verifique a assinatura HMAC, credite o pedido uma vez e veja o pagamento cair no seu saldo.
Um arquivo, sem dependências. createInvoice(), getInvoice() e verifyWebhook() — insira em qualquer projeto.
As solicitações e webhooks são assinados com HMAC-SHA256 com desvio de timestamp e chaves de idempotência.
JSON simples sobre HTTPS — integre de qualquer stack, não apenas PHP.
<?php
require 'Payora.php';
$payora = new Payora('https://api.payora.money', getenv('PAYORA_KEY'), getenv('PAYORA_SECRET'));
// 1 — create an invoice (fiat-priced; the payer picks a coin)
$inv = $payora->createInvoice([
'order_id' => 'ORDER-42',
'mode' => 'fiat',
'amount' => '9.99',
'return_url' => 'https://shop.example/thanks',
'lang' => 'en',
], 'ORDER-42'); // Idempotency-Key: a retry never creates a second invoice
header('Location: ' . $inv['pay_url']);
// 2 — webhook endpoint: ALWAYS verify the signature first
$event = $payora->verifyWebhook(file_get_contents('php://input'), getallheaders());
if ($event === null) { http_response_code(400); exit; }
if ($event['status'] === 'paid') {
creditOrderOnce($event['id'], $event['order_id'], $event['amount'], $event['currency']);
}
http_response_code(200); // 2xx stops retriesconst Payora = require('./payora');
const payora = new Payora('https://api.payora.money', process.env.PAYORA_KEY, process.env.PAYORA_SECRET);
// 1 — create an invoice and redirect
app.post('/checkout', async (req, res) => {
const inv = await payora.createInvoice({ order_id: 'ORDER-42', mode: 'fiat', amount: '9.99' }, 'ORDER-42');
res.redirect(inv.pay_url);
});
// 2 — webhook: verify over the RAW body
app.post('/payora/webhook', express.raw({ type: '*/*' }), (req, res) => {
const event = payora.verifyWebhook(req.body, req.headers);
if (event === null) return res.status(400).end();
if (event.status === 'paid') creditOrderOnce(event.id, event.order_id);
res.status(200).end();
});import os
from payora import Payora
payora = Payora('https://api.payora.money', os.environ['PAYORA_KEY'], os.environ['PAYORA_SECRET'])
# 1 — create an invoice and redirect
inv = payora.create_invoice({'order_id': 'ORDER-42', 'mode': 'fiat', 'amount': '9.99'}, 'ORDER-42')
return redirect(inv['pay_url'])
# 2 — webhook: verify over the RAW body
event = payora.verify_webhook(request.get_data(), dict(request.headers))
if event is None:
return ('', 400)
if event['status'] == 'paid':
credit_order_once(event['id'], event['order_id'])
return ('', 200)# signature = lowercase hex HMAC-SHA256(api_secret, timestamp + "." + raw_body)
BODY='{"order_id":"ORDER-42","mode":"fiat","amount":"9.99"}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$PAYORA_SECRET" | cut -d' ' -f2)
curl -X POST https://api.payora.money/v1/invoice \
-H "X-Payora-Key: $PAYORA_KEY" -H "X-Payora-Timestamp: $TS" \
-H "X-Payora-Signature: $SIG" -H 'Idempotency-Key: ORDER-42' \
-H 'Content-Type: application/json' -d "$BODY"
# → 201 { "invoice_id": …, "status": "pending", "pay_url": "https://pay.payora.money/i/…", "expires": … }Obtenha sua chave de API e segredo ao criar uma conta. O SDK completo está no seu painel.
Cada chamada, exceto /v1/health, carrega três cabeçalhos assinados. A assinatura prova que a solicitação vem do detentor do seu api_secret e não foi alterada no caminho.
| Cabeçalho | Valor | Descrição |
|---|---|---|
X-Payora-Key | pk_… | Seu api_key público. Identifica a loja. |
X-Payora-Timestamp | unix seconds | O momento em que você assinou a solicitação, em segundos Unix. |
X-Payora-Signature | hex · 64 | HMAC-SHA256 em hex minúsculo de timestamp + "." + corpo bruto, chaveado com seu api_secret. |
X-Payora-Test | 1 | Marca uma fatura como um teste da sua integração: é real e pode receber moedas, mas fica fora dos relatórios de demanda e conversão. |
Idempotency-Key | string | Opcional em POST /v1/invoice e POST /v1/payout. Uma nova tentativa com a mesma chave retorna o primeiro resultado em vez de criar um duplicado; a mesma chave com um corpo diferente responde 409. |
Content-Type | application/json | Obrigatório em solicitações que carregam um corpo. |
hex( HMAC-SHA256( api_secret, timestamp + "." + raw_body ) )Assine os bytes exatos que você envia. Recodificar o JSON após a assinatura — até mesmo reordenar chaves ou adicionar um espaço — quebra a assinatura.
Para uma solicitação GET, o corpo está vazio, então a string assinada é o timestamp seguida de um ponto.
A API rejeita um timestamp mais de 120 segundos distante de seu relógio. Mantenha seu servidor sincronizado com NTP.
Mantenha o api_secret em seu servidor. Ele assina solicitações e webhooks da mesma forma: quem o possui pode criar faturas em seu nome e forjar callbacks.
<?php
$body = json_encode(['order_id' => 'ORDER-42', 'mode' => 'fiat', 'amount' => '9.99'], JSON_UNESCAPED_SLASHES);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $body, $apiSecret); // lowercase hex
$ch = curl_init('https://api.payora.money/v1/invoice');
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-Payora-Key: ' . $apiKey,
'X-Payora-Timestamp: ' . $ts,
'X-Payora-Signature: ' . $sig,
'Idempotency-Key: ORDER-42',
'Content-Type: application/json',
],
]);
$invoice = json_decode(curl_exec($ch), true);const crypto = require('crypto');
const body = JSON.stringify({ order_id: 'ORDER-42', mode: 'fiat', amount: '9.99' });
const ts = String(Math.floor(Date.now() / 1000));
const sig = crypto.createHmac('sha256', API_SECRET).update(ts + '.' + body).digest('hex');
const res = await fetch('https://api.payora.money/v1/invoice', {
method: 'POST',
headers: {
'X-Payora-Key': API_KEY,
'X-Payora-Timestamp': ts,
'X-Payora-Signature': sig,
'Idempotency-Key': 'ORDER-42',
'Content-Type': 'application/json',
},
body, // send exactly the bytes you signed
});import hashlib, hmac, json, time, urllib.request
body = json.dumps({'order_id': 'ORDER-42', 'mode': 'fiat', 'amount': '9.99'}, separators=(',', ':'))
ts = str(int(time.time()))
sig = hmac.new(API_SECRET.encode(), (ts + '.' + body).encode(), hashlib.sha256).hexdigest()
req = urllib.request.Request('https://api.payora.money/v1/invoice', data=body.encode(), method='POST', headers={
'X-Payora-Key': API_KEY,
'X-Payora-Timestamp': ts,
'X-Payora-Signature': sig,
'Idempotency-Key': 'ORDER-42',
'Content-Type': 'application/json',
})
invoice = json.load(urllib.request.urlopen(req))# GET has an empty body: the signed string is just the timestamp and a dot
TS=$(date +%s)
SIG=$(printf '%s.' "$TS" | openssl dgst -sha256 -hmac "$PAYORA_SECRET" | cut -d' ' -f2)
curl https://api.payora.money/v1/invoice/1042 \
-H "X-Payora-Key: $PAYORA_KEY" \
-H "X-Payora-Timestamp: $TS" \
-H "X-Payora-Signature: $SIG"Todos opcionais, exceto order_id e amount. O modo fiat permite que o pagador escolha qualquer moeda habilitada em sua conta; o modo cripto também precisa de currency.
| Parâmetro | Tipo | Descrição |
|---|---|---|
order_id | string · required | Sua referência de pedido única (≤190 caracteres). Uma repetição é rejeitada com 409 — seguro contra envios duplicados. |
amount | string · required | Valor fiat (modo=fiat) ou valor exato em cripto (modo=crypto). |
mode | fiat | crypto | Fiat padrão: taxa bloqueada por moeda no checkout. O cripto fixa a moeda + valor antecipadamente. |
fiat_currency | string | Código fiat ISO para modo fiat (padrão USD). |
currency | string | Moeda para modo cripto (por exemplo, TON, TRX, USDT_TRON). |
return_url | https URL | Onde o botão do checkout “Return to store” envia o cliente de volta — seu site. Apenas http(s) absoluto. |
lang | en·ru·uk·es·de | Idioma do checkout, para que um cliente da sua loja russa veja o checkout em russo — não em inglês. Também pode ser definido como ?lang=ru na URL de pagamento. |
ttl | seconds | Quanto tempo a fatura permanece pagável (120–86400 segundos, padrão 1800). |
customer_email | Opcional — recibo + enviado por e-mail ao pagador. | |
notes | string | Nota em formato livre armazenada na fatura. |
return_url e lang também funcionam como parâmetros de consulta anexados ao pay_url que a API fornece — <pay_url>&lang=ru&return_url=https://shop.example/thanks. Sempre envie o comprador para o pay_url retornado pela API: ele carrega um token de acesso por fatura, então uma página de checkout não pode ser acessada adivinhando números de fatura. Não reconstrua o link a partir do id da fatura.
Preencha os campos e copie um comando cURL pronto. Ele se assina em seu shell com $PAYORA_KEY e $PAYORA_SECRET — esta página nunca vê suas chaves e não envia nada.
BODY='{"order_id":"ORDER-42","mode":"fiat","amount":"9.99","fiat_currency":"USD","return_url":"https://shop.example/thanks","lang":"pt","ttl":1800}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$PAYORA_SECRET" | cut -d' ' -f2)
curl -X POST https://api.payora.money/v1/invoice \
-H "X-Payora-Key: $PAYORA_KEY" \
-H "X-Payora-Timestamp: $TS" \
-H "X-Payora-Signature: $SIG" \
-H 'Idempotency-Key: ORDER-42' \
-H 'Content-Type: application/json' \
-d "$BODY"Nada é enviado desta página.
Quando uma fatura ou um pagamento muda de estado, a Payora envia um evento JSON assinado para sua URL de callback. Verifique a assinatura primeiro, credite o pedido uma vez, responda 2xx.
| Evento | status | Quando é acionado |
|---|---|---|
invoice.paid | paid | O pagamento é confirmado na blockchain. Carrega o valor, a moeda e tx_hash. |
invoice.underpaid | underpaid | A fatura expirou após menos do que o valor esperado ter chegado. |
invoice.expired | expired | A fatura expirou sem nada recebido. |
invoice.cancelled | cancelled | A fatura foi cancelada. O dinheiro que já havia chegado, se houver, é descrito no evento. |
invoice.cancel_settled | — | O dinheiro que chegou em uma fatura cancelada foi tratado: creditado ou devolvido. |
invoice.late_payment | — | Dinheiro que chegou em uma fatura após ser cancelada. Enviado uma vez para cada depósito desse tipo; o resultado diz se foi creditado ou está sendo devolvido. |
payout.sent | sent | Um lote de pagamento foi assinado e transmitido. Carrega cada item com seu tx_hash. |
| Cabeçalho | Valor | Descrição |
|---|---|---|
X-Payora-Id | uuid | ID de evento único, o mesmo que o id no corpo. Armazene-o para ignorar repetições. |
X-Payora-Event | invoice.paid | Nome do evento. |
X-Payora-Timestamp | unix seconds | Quando esta tentativa foi assinada. |
X-Payora-Signature | hex · 64 | Mesma estrutura que os pedidos: HMAC-SHA256 de timestamp + "." + corpo bruto com seu api_secret. |
| Campo | Tipo | Descrição |
|---|---|---|
id | uuid | ID do evento para desduplicação. |
event | string | Nome do evento. |
invoice_id | int | Número da fatura Payora. |
order_id | string | Sua referência de pedido, conforme enviada quando a fatura foi criada. |
status | string | paid para invoice.paid. |
currency | string | Moeda utilizada pelo pagador, ex. USDT_TRON. |
amount | decimal string | Valor recebido. |
amount_units | integer string | O mesmo valor nas menores unidades da moeda — use para comparações exatas. |
expected | decimal string | Valor que a fatura solicitou. |
fiat_amount | decimal string | null | Preço fiat da fatura como você a criou; nulo para faturas em modo cripto. |
fiat_currency | string | null | Código ISO de fiat_amount; nulo para faturas em modo cripto. |
tx_hash | string | Hash da transação on-chain. |
paid_at | unix seconds | Quando o evento foi criado. |
test | bool | true para faturas de sandbox. |
{
"id": "6f1c2a4e-8b0d-4c1e-9a57-2f3d9e1b7c40",
"event": "invoice.paid",
"invoice_id": 1042,
"order_id": "ORDER-42",
"status": "paid",
"currency": "USDT_TRON",
"amount": "9.99",
"amount_units": "9990000",
"expected": "9.99",
"fiat_amount": "9.99",
"fiat_currency": "USD",
"tx_hash": "3f9a…c21e",
"paid_at": 1758038400,
"test": false
}Quando o valor recebido difere da fatura, amount_received e amount_expected são adicionados.
Qualquer coisa diferente de 2xx, ou nenhuma resposta dentro de 15 segundos, é tentada novamente com retrocesso exponencial limitado a uma hora entre as tentativas — até 12 tentativas. Cada tentativa é assinada novamente com um novo timestamp; o corpo e o ID do evento permanecem os mesmos, então desduplicar pelo ID.
Após a última tentativa, o evento é marcado como falhado e o proprietário da loja recebe um e-mail. Redirecionamentos nunca são seguidos, e a URL de callback deve ser acessível pela internet — sem localhost ou endereços privados.
hash_equals, crypto.timingSafeEqual, hmac.compare_digest.<?php
require 'Payora.php';
$payora = new Payora('https://api.payora.money', getenv('PAYORA_KEY'), getenv('PAYORA_SECRET'));
$raw = file_get_contents('php://input'); // raw, before any parsing
$event = $payora->verifyWebhook($raw, getallheaders()); // HMAC + ±300 s window, constant-time
if ($event === null) { http_response_code(400); exit; } // bad / forged / stale
if ($event['event'] === 'invoice.paid' && !alreadyProcessed($event['id'])) {
creditOrder($event['order_id'], $event['amount'], $event['currency'], $event['tx_hash']);
rememberProcessed($event['id']);
}
http_response_code(200); // 2xx stops retries// Express: capture the RAW body for this route
app.post('/payora/webhook', express.raw({ type: '*/*' }), (req, res) => {
const event = payora.verifyWebhook(req.body, req.headers); // HMAC + ±300 s, timingSafeEqual
if (event === null) return res.status(400).end();
if (event.event === 'invoice.paid' && !alreadyProcessed(event.id)) {
creditOrder(event.order_id, event.amount, event.currency, event.tx_hash);
rememberProcessed(event.id);
}
res.status(200).end(); // 2xx stops retries
});# Flask: request.get_data() is the exact raw body
@app.post('/payora/webhook')
def payora_webhook():
event = payora.verify_webhook(request.get_data(), dict(request.headers))
if event is None:
return ('', 400) # bad / forged / stale
if event['event'] == 'invoice.paid' and not already_processed(event['id']):
credit_order(event['order_id'], event['amount'], event['currency'], event['tx_hash'])
remember_processed(event['id'])
return ('', 200) # 2xx stops retries# Recompute the signature of a delivery you saved byte-for-byte to body.json
TS='1758038400' # X-Payora-Timestamp
SIG='…' # X-Payora-Signature
EXPECTED=$(printf '%s.' "$TS" | cat - body.json | openssl dgst -sha256 -hmac "$PAYORA_SECRET" | cut -d' ' -f2)
[ "$EXPECTED" = "$SIG" ] && echo valid || echo forgedInsira um segredo, um timestamp e o corpo bruto para ver a assinatura exata que a Payora enviaria — ou verifique uma que você recebeu.
Executa no seu navegador com WebCrypto. Nada do que você digita sai desta página. Use um segredo de teste, não um ativo, em um computador compartilhado.
1758038400.{…}X-Payora-Timestamp: 1758038400
X-Payora-Signature: …Cole uma assinatura para comparar
Envie cripto para até 500 carteiras em uma solicitação assinada e idempotente — para payroll, pagamentos de afiliados ou retiradas. O total do lote mais a taxa por item é mantido em seu saldo interno instantaneamente; o operador assina e transmite, então um webhook assinado payout.sent é acionado. A mesma autenticação HMAC que tudo o mais.
# create a payout batch — funds held instantly, sent by the operator
curl -X POST https://api.payora.money/v1/payout \
-H 'X-Payora-Key: pk_…' -H 'X-Payora-Timestamp: 1700000000' \
-H 'X-Payora-Signature: <hmac-sha256>' -H 'Idempotency-Key: payroll-2026-01' \
-d '{"currency":"USDT_TRON","items":[
{"address":"TR7…","amount":"250.00"},
{"address":"TX9…","amount":"99.50","tag":"batch-A"}]}'
# → 201 Created
{ "batch_id": 812, "status": "pending", "currency": "USDT_TRON",
"item_count": 2, "total": "349.50", "fee": "…", "items": [ … ] }
# poll status, or receive a signed payout.sent webhook when it is sent
curl https://api.payora.money/v1/payout/812 -H 'X-Payora-Key: …' …<?php
// The one-file PHP SDK covers invoices and webhooks; payouts are one signed POST.
$body = json_encode(['currency' => 'USDT_TRON', 'items' => [
['address' => 'TR7…', 'amount' => '250.00'],
['address' => 'TX9…', 'amount' => '99.50', 'tag' => 'batch-A'],
]], JSON_UNESCAPED_SLASHES);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $body, $apiSecret);
$ch = curl_init('https://api.payora.money/v1/payout');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-Payora-Key: ' . $apiKey, 'X-Payora-Timestamp: ' . $ts, 'X-Payora-Signature: ' . $sig,
'Idempotency-Key: payroll-2026-01', 'Content-Type: application/json']]);
$batch = json_decode(curl_exec($ch), true); // 201: batch_id, status, totals, fee, itemsconst batch = await payora.createPayout({
currency: 'USDT_TRON',
items: [
{ address: 'TR7…', amount: '250.00' },
{ address: 'TX9…', amount: '99.50', tag: 'batch-A' },
],
}, 'payroll-2026-01'); // Idempotency-Key: a retried run never doubles
const status = await payora.getPayout(batch.batch_id);
// still pending? await payora.cancelPayout(batch.batch_id) releases the holdbatch = payora.create_payout({
'currency': 'USDT_TRON',
'items': [
{'address': 'TR7…', 'amount': '250.00'},
{'address': 'TX9…', 'amount': '99.50', 'tag': 'batch-A'},
],
}, 'payroll-2026-01') # Idempotency-Key: a retried run never doubles
status = payora.get_payout(batch['batch_id'])
# still pending? payora.cancel_payout(batch['batch_id']) releases the holdA validação é rigorosa: qualquer endereço inválido ou valor excessivamente preciso rejeita todo o lote (HTTP 422) com os índices dos itens problemáticos — uma execução de folha de pagamento nunca descarta silenciosamente um destinatário. Cancele um lote ainda pendente com POST /v1/payout/{id}/cancel para liberar a retenção. Veja o artigo sobre a arquitetura.
Cada endpoint fala JSON simples sobre HTTPS em api.payora.money. Todos, exceto /v1/health, usam a mesma autenticação de solicitação HMAC-SHA256. A especificação legível por máquina está em openapi.json.
| Endpoint | Acesso | Descrição |
|---|---|---|
GET/v1/health | no auth | Status do serviço mais a lista de moedas habilitadas. |
POST/v1/invoice | auth | Crie uma fatura (modo fiat ou cripto). Suporta Idempotency-Key. Retorna 201 com invoice_id, status, pay_url e expires; o modo cripto adiciona o endereço, valor e deeplink. |
GET/v1/invoice/{id} | auth | Status da fatura (apenas faturas próprias): status, remaining, e o charge — moeda, endereço, valores esperados/recebidos e tx_hash. |
POST/v1/payout | auth · Pro+ | Crie um lote de pagamento em massa (validação rigorosa, fundos retidos instantaneamente). Suporta Idempotency-Key. Retorna 201 com a visualização do lote: batch_id, status, totais, taxa, itens. |
GET/v1/payout | auth | Liste seus lotes de pagamento recentes (?limit=, padrão 50). |
GET/v1/payout/{id} | auth | Status do lote de pagamento e itens (apenas lotes próprios). |
POST/v1/payout/{id}/cancel | auth | Cancele um lote ainda pendente e libere o saldo retido. Retorna 409 se o lote não puder mais ser cancelado. |
Nenhum endpoint corresponde.
Arquivos únicos sem dependências. Cada SDK assina solicitações e verifica webhooks da mesma forma.
PHP 7.4+ com cURL, um arquivo. createInvoice, getInvoice e verifyWebhook.
Node.js com https e crypto integrados apenas. Faturas, saldo, pagamentos e verifyWebhook.
Apenas biblioteca padrão do Python. Faturas, saldo, pagamentos e verify_webhook.
Uma coleção do Postman que assina cada chamada para você.
A especificação legível por máquina de cada endpoint, para geradores de código e clientes de API.
Um módulo pronto faz tudo isso por você: fatura, redirecionamento e um webhook verificado.
Respostas diretas, incluindo as desconfortáveis: custódia, taxas e o que acontece quando algo dá errado.
Centro de ajudaInstale o SDK PHP de arquivo único (sem dependências) ou chame a API REST diretamente. Crie uma fatura com createInvoice(), redirecione o cliente para seu pay_url e trate um evento de webhook: status=paid. Um desenvolvedor competente está ativo em 30–60 minutos.
Sim. Tudo é JSON simples sobre HTTPS, então você pode integrar de qualquer linguagem. O SDK PHP é um wrapper de conveniência em torno dos mesmos endpoints — criar fatura, obter fatura e verificar assinaturas de webhook.
Sim. Passe return_url ao criar a fatura (ou ?return_url= no link de pagamento) e o checkout mostrará um botão “Retornar à loja” de volta ao seu site na tela de sucesso — e enquanto paga. Passe lang (en, ru, uk, es, de), ou ?lang= no link, para que um cliente da sua loja russa chegue ao checkout russo em vez do inglês. Ambos são opcionais; return_url deve ser uma URL http(s) absoluta.
As solicitações e webhooks são autenticados com HMAC-SHA256 sobre o timestamp e o corpo bruto usando seu api_secret, com uma janela de desvio de ±120 segundos e chaves de idempotência. As assinaturas são comparadas em tempo constante para prevenir ataques de temporização.
Crie uma conta gratuita. Sua api_key pública e api_secret secreta aparecem no painel, junto com o SDK para download e a referência completa de webhook. Gire as chaves a qualquer momento nas configurações.
Um evento JSON assinado com o id da fatura, seu order_id, o status (por exemplo, pago), o valor e a moeda, e um id de evento único para idempotência. Sempre verifique a assinatura antes de creditar um pedido, depois registre o id do evento para evitar processamento duplo em tentativas.
Sim. POST /v1/payout envia criptomoeda para até 500 carteiras em uma única solicitação — um {endereço, valor, tag opcional} por item, em qualquer moeda habilitada em sua conta. Ele usa a mesma autenticação HMAC-SHA256 e Idempotency-Key que a API de fatura, então uma solicitação reprocessada nunca cria um lote duplicado. O total do lote mais a taxa por item é reservado em seu saldo imediatamente; o operador assina e transmite, então um webhook de pagamento assinado é acionado. A validação é rigorosa — qualquer endereço inválido ou valor excessivamente preciso rejeita todo o lote (422), então uma execução de folha de pagamento nunca descarta silenciosamente um destinatário.
Construa a lista de destinatários em seu próprio sistema, depois chame POST /v1/payout uma vez por execução com uma Idempotency-Key estável (por exemplo, payroll-2026-01). Consulte GET /v1/payout/{id} ou aguarde o webhook payout.sent para confirmar a entrega e registrar cada tx hash. Enviar o lote reserva fundos, mas não os move por si só — o operador assina e transmite, então nada sai apenas com uma chamada de API.
Um único SDK PHP sem dependências: crie faturas, redirecione para o checkout hospedado e verifique webhooks assinados. REST está disponível para qualquer linguagem.