PayZuDocs

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=.

Próximos passos

Nesta página