Primeiros passos
Da credencial criada no painel à primeira cobrança paga, confirmada por webhook no seu servidor.
As chamadas deste guia vão para produção: a cobrança criada aqui é real.
Criar a credencial
No painel da Conta Digital, em hub.payzu.com.br, abra a área de credenciais e crie uma com os escopos que a integração usa. A criação pede o PIN de operação do titular.
Para este guia, marque PAYMENT_WRITE, PAYMENT_READ e WEBHOOK_WRITE. O que cada escopo libera está em Escopos.
A tela mostra o client_id, o client_secret e o token da credencial (pzu_…).
O client_secret aparece uma vez só. Guarde-o antes de sair da tela.
Trocar a credencial por um token
Mande o client_id e o client_secret para POST /oauth/token. O token devolvido vale 15 minutos.
curl -X POST https://api.hub.payzu.com.br/api/v1/oauth/token \
-u "$PAYZU_CLIENT_ID:$PAYZU_CLIENT_SECRET" \
-d 'grant_type=client_credentials'const credentials = Buffer.from(`${process.env.PAYZU_CLIENT_ID}:${process.env.PAYZU_CLIENT_SECRET}`).toString('base64');
const response = await fetch('https://api.hub.payzu.com.br/api/v1/oauth/token', {
method: 'POST',
headers: {
Authorization: `Basic ${credentials}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'grant_type=client_credentials',
});
const { access_token, expires_in } = await response.json();{
"access_token": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..mQ3Zy1hbVhpbXBsZQ.ZXhlbXBsbw.c2lnbmF0dXJl",
"token_type": "Bearer",
"expires_in": 900,
"scope": "PAYMENT_WRITE PAYMENT_READ WEBHOOK_WRITE"
}Mande o access_token em Authorization: Bearer nas outras chamadas. Nos exemplos a seguir, ele está em $PAYZU_TOKEN. Quando o token vence, a API responde 401 com TOKEN_INVALID: peça outro na mesma rota.
Cadastrar o webhook
Cadastre a URL do seu servidor que vai receber os webhooks, com POST /transactions/webhooks (escopo WEBHOOK_WRITE). A URL precisa ser HTTPS e pública.
curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/webhooks \
-H "Authorization: Bearer $PAYZU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://sualoja.com.br/webhooks/payzu",
"events": ["PAYMENT_PAID", "PAYMENT_EXPIRED"]
}'const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/webhooks', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://sualoja.com.br/webhooks/payzu',
events: ['PAYMENT_PAID', 'PAYMENT_EXPIRED'],
}),
});
const { id, secret } = await res.json();A resposta 201 traz o secret que assina cada webhook. Ele só aparece nessa resposta: guarde-o. O cadastro também pode ser feito no painel.
Se vier 403 com TOKEN_MISSING_SCOPE, falta um escopo na credencial; o nome dele vem em details.scope.
Criar a cobrança
Crie uma cobrança com POST /transactions/payment (escopo PAYMENT_WRITE). O valor vai em centavos: 1500 é R$ 15,00.
curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/payment \
-H "Authorization: Bearer $PAYZU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"amount": 1500,
"method": "PIX",
"description": "Pedido 4821",
"externalRef": "pedido-4821",
"metadata": { "pedido": "4821", "canal": "checkout-web" },
"customer": { "name": "Maria Souza", "document": "52998224725" }
}'const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/payment', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 1500,
method: 'PIX',
description: 'Pedido 4821',
externalRef: 'pedido-4821',
metadata: { pedido: '4821', canal: 'checkout-web' },
customer: { name: 'Maria Souza', document: '52998224725' },
}),
});
const cobranca = await res.json();A resposta 201 traz a cobrança com status: "PENDING" e o Pix copia e cola em pix.qrCodeText. Mostre-o ao cliente e gere o QR Code a partir dele. Repetir a chamada com o mesmo externalRef devolve a mesma cobrança (200), sem criar outra.
Receber o PAYMENT_PAID
Quando o cliente paga, o seu servidor recebe o PAYMENT_PAID:
POST /webhooks/payzu
Content-Type: application/json
X-Payzu-Event: PAYMENT_PAID
X-Payzu-Delivery: cmu1r7x2k000a01s6h4f2b9qd
X-Payzu-Timestamp: 1791210790441
X-Payzu-Signature: sha256=8f3b2c1d...
{
"event": "PAYMENT_PAID",
"id": "cmu1r7x2k000a01s6h4f2b9qd",
"sentAt": "2026-10-05T14:33:10.441Z",
"accountId": "cmu0z8k2a000001s6acct0001",
"data": {
"paymentId": "cmu2wbljx0000e8gtlic8q1gi",
"status": "PAID",
"amount": 1500,
"serviceFee": 105,
"netAmount": 1395,
"metadata": { "pedido": "4821", "canal": "checkout-web" },
"externalRef": "pedido-4821",
"endToEndId": "E99999999202610051433a1b2c3d4e5f"
}
}Confira a assinatura com o secret do cadastro do webhook, como em Webhooks, e responda com qualquer 2xx em até 10 segundos. Libere o pedido aqui, no PAYMENT_PAID: o externalRef e o metadata da criação voltam em data.
Consultar sem esperar o webhook
Consulte a cobrança em GET /transactions/payment/{paymentId} (escopo PAYMENT_READ), com o id da resposta de criação ou o paymentId do webhook:
curl https://api.hub.payzu.com.br/api/v1/transactions/payment/hubp-20261005K7Q2M9XB4T127431 \
-H "Authorization: Bearer $PAYZU_TOKEN"const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/payment/hubp-20261005K7Q2M9XB4T127431', {
headers: {
Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
},
});
const cobranca = await res.json();Para achar a cobrança de um pedido, use Listar cobranças com ?externalRef=.