Payze Payze Documentação da API api.pagpayze.com.br

Começar

API de pagamentos da Payze

Crie cobranças PIX, Bizum e SPEI a partir do seu sistema e receba a confirmação por webhook. REST, JSON e autenticação por API Key.

Como funciona

01Seu servidor cria a cobrançaPOST /api/v1/direct-payments com valor, método e comprador, autenticado pela API Key.
02O comprador pagaVocê mostra o que veio em payment_data: copia-e-cola, formulário ou CLABE.
03A Payze avisaWebhook no seu servidor. A venda está paga quando o status é AUTHORIZED.

A criação devolve a cobrança com status PENDING. A confirmação chega depois, quando o banco do comprador conclui o pagamento: por webhook ou pela consulta de status.

Métodos de pagamento

Você recebe sempre em reais

No Bizum e no SPEI o comprador paga em euros ou pesos. A Payze converte o valor para reais pela cotação da plataforma, e taxas e saldo são calculados em BRL. Os métodos internacionais precisam estar liberados no plano da sua conta; se não estiverem, a API recusa a cobrança e você deve falar com o suporte.

Endereço da API

https://api.pagpayze.com.br

Requisições e respostas usam JSON. Envie Content-Type: application/json nas requisições com corpo.

Endpoints

MétodoCaminhoAutenticaçãoUso
POST/api/v1/direct-paymentsHeader X-API-KeyCriar uma cobrança
GET/api/v1/payments/{transaction_id}/statusNenhumaConsultar o status de uma transação

Formato das respostas

Toda resposta tem o campo hasError. Com sucesso, os dados vêm em data; com erro, a mensagem vem em error (veja Erros).

{
  "hasError": false,
  "data": { "transaction_id": "7KQ2M9XA4T1B", "status": "PENDING" }
}
{
  "hasError": true,
  "error": "API key não fornecida. Envie a chave no header X-API-Key",
  "errorFields": [],
  "statusCode": 401,
  "timestamp": "2026-10-08T15:19:01.612Z",
  "path": "/api/v1/direct-payments"
}

Conceitos

  • Transação. Cada cobrança criada gera uma transação, identificada por transaction_id (12 caracteres, letras maiúsculas e números). Guarde esse valor junto com o seu pedido: é ele que liga a criação, a consulta de status e o webhook.
  • Valores. Na criação, amount é um inteiro em centavos da moeda da cobrança. Nas respostas, os valores vêm em unidades decimais (99.9 = R$ 99,90). Detalhes em Valores e limites.
  • Produção. As chaves de API são de produção (pk_live_…) e não existe modo de teste separado: toda cobrança criada é real. Para testar a integração, crie um PIX de valor baixo e pague você mesmo.

Começar

Início rápido

Sua primeira cobrança PIX em quatro passos. Esse é o fluxo inteiro: nos outros métodos mudam só o paymentMethod, alguns campos do comprador e o que você mostra na tela.

  1. Gere uma API Key

    No painel da Payze, abra Integração → API Keys e clique em Nova API Key. Copie a chave (pk_live_…) na hora: ela aparece uma única vez. Guarde-a numa variável de ambiente do seu servidor, por exemplo PAYZE_API_KEY.

  2. Crie a cobrança

    Chame o endpoint de cobrança a partir do seu servidor. amount vai em centavos: 9990 = R$ 99,90.

    curl -X POST https://api.pagpayze.com.br/api/v1/direct-payments \
      -H "Content-Type: application/json" \
      -H "X-API-Key: $PAYZE_API_KEY" \
      -d '{
        "amount": 9990,
        "description": "Pedido 1234",
        "paymentMethod": "pix",
        "customer": {
          "name": "João da Silva",
          "email": "joao@exemplo.com",
          "document": "12345678909"
        }
      }'
    const res = await fetch("https://api.pagpayze.com.br/api/v1/direct-payments", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-API-Key": process.env.PAYZE_API_KEY,
      },
      body: JSON.stringify({
        amount: 9990, // R$ 99,90 em centavos
        description: "Pedido 1234",
        paymentMethod: "pix",
        customer: {
          name: "João da Silva",
          email: "joao@exemplo.com",
          document: "12345678909",
        },
      }),
    });
    const body = await res.json();
    if (!res.ok) throw new Error(body.error);
    
    const { transaction_id, payment_data } = body.data;
    // Salve transaction_id no seu pedido antes de seguir.
    $payload = [
      "amount" => 9990, // R$ 99,90 em centavos
      "description" => "Pedido 1234",
      "paymentMethod" => "pix",
      "customer" => [
        "name" => "João da Silva",
        "email" => "joao@exemplo.com",
        "document" => "12345678909",
      ],
    ];
    
    $ch = curl_init("https://api.pagpayze.com.br/api/v1/direct-payments");
    curl_setopt_array($ch, [
      CURLOPT_POST => true,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "X-API-Key: " . getenv("PAYZE_API_KEY"),
      ],
      CURLOPT_POSTFIELDS => json_encode($payload),
    ]);
    $body = json_decode(curl_exec($ch), true);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($http >= 400) throw new Exception($body["error"]);
    $transactionId = $body["data"]["transaction_id"]; // salve no seu pedido
    {
      "hasError": false,
      "data": {
        "transaction_id": "7KQ2M9XA4T1B",
        "total_value": 99.9,
        "status": "PENDING",
        "email": "joao@exemplo.com",
        "payment_method": "pix",
        "payment_data": {
          "expiration_date": null,
          "payment_id": "c1a7e0b2-5d3f-4e8a-9b61-0f2d7c4e9a13",
          "pix_key": "00020126580014br.gov.bcb.pix0136…6304A1B2",
          "status": "PENDING",
          "status_detail": "WAITING_PAYMENT",
          "total_transaction_value": 99.9
        }
      }
    }
  3. Mostre o PIX ao comprador

    payment_data.pix_key é o código copia-e-cola. Mostre-o com um botão de copiar e gere o QR Code a partir dele com a biblioteca de QR Code que preferir. Envie ao navegador só o que ele precisa exibir, nunca a API Key.

  4. Confirme o pagamento

    Cadastre a URL do seu servidor em Integração → Webhooks. Quando o PIX for pago, a Payze envia um POST com "status": "AUTHORIZED". Confirme na consulta de status e libere o pedido.

    curl https://api.pagpayze.com.br/api/v1/payments/7KQ2M9XA4T1B/status
Só AUTHORIZED é pagamento confirmado

A resposta da criação traz a cobrança ainda pendente. Libere o pedido apenas quando o seu servidor receber ou consultar o status AUTHORIZED.

Próximos passos

Começar

Autenticação

A criação de cobranças é autenticada por API Key, enviada no header X-API-Key. Cada chave pertence a uma conta: as cobranças criadas com ela entram nessa conta.

Criar uma API Key

  1. No painel da Payze, abra Integração → API Keys.
  2. Clique em Nova API Key, dê um nome (3 a 100 caracteres) e, se quiser, uma descrição.
  3. Copie a chave exibida. Ela aparece uma única vez: a Payze guarda só um hash da chave e não consegue mostrá-la de novo. Se perder, crie outra.

Formato

A chave tem o prefixo pk_live_ seguido de 48 caracteres hexadecimais (0-9 e a-f), 56 caracteres no total. Uma chave fora desse formato é recusada antes de qualquer outra verificação.

pk_live_0123456789abcdef0123456789abcdef0123456789abcdef

Enviar a chave

POST /api/v1/direct-payments HTTP/1.1
Host: api.pagpayze.com.br
Content-Type: application/json
X-API-Key: pk_live_…

A consulta de status não usa API Key.

Gerenciar chaves

  • Limite: até 10 chaves ativas por conta.
  • Pausar: em Editar, mude o status para pausada. A API passa a recusar a chave até você reativá-la.
  • Deletar: remove a chave de vez. Chamadas com ela passam a receber 401.

Boas práticas

  • Use a chave só no servidor. Nunca a coloque em front-end, app mobile ou repositório de código.
  • Guarde-a em variável de ambiente ou num cofre de segredos.
  • Crie uma chave por integração: dá para trocar ou pausar uma sem afetar as outras.
  • Se suspeitar de vazamento, delete a chave e crie outra.

Erros de autenticação

Todos respondem HTTP 401, com a mensagem em error:

MensagemCausa
API key não fornecida. Envie a chave no header X-API-KeyHeader ausente.
Formato de API key inválidoO valor não segue pk_live_ + 48 caracteres hexadecimais (confira espaços e quebras de linha).
API key inválidaChave inexistente ou deletada.
API key está inativa ou revogadaChave pausada. Reative no painel.
Seller está bloqueado para receber pagamentosConta bloqueada. Fale com o suporte.

Cobranças

Criar cobrança

POST/api/v1/direct-paymentsHeader X-API-Key

Cria uma cobrança para um comprador, sem produto cadastrado na Payze. O mesmo endpoint atende todos os métodos: o paymentMethod define a moeda, os dados exigidos do comprador e o que volta em payment_data.

Corpo da requisição

CampoTipoObrigatórioDescrição
amountinteiroobrigatórioValor em centavos da moeda da cobrança: centavos de real no pix, de euro no bizum e de peso mexicano no spei. Ex.: 9990 = R$ 99,90. Mínimos em Valores e limites.
descriptionstringobrigatórioDescrição da cobrança, de 3 a 255 caracteres.
paymentMethodstringobrigatóriopix, bizum ou spei.
customerobjetoobrigatórioDados do comprador (abaixo).
returnUrlstringcondicionalObrigatório no bizum. URL https (até 2048 caracteres) da página para onde o comprador volta depois de aprovar no banco.
sourceUrlstringopcionalUsado no bizum e no spei. URL https (até 2048 caracteres) da página do seu site de onde a cobrança se origina. Sem ela, vale a URL do checkout da plataforma.
Campos desconhecidos são recusados

A API responde 400 se o corpo tiver um campo que ela não conhece (por exemplo currency). A moeda é sempre a do método.

Objeto customer

CampoTipoObrigatórioDescrição
namestringobrigatórioNome completo, de 3 a 128 caracteres.
emailstringobrigatórioE-mail válido do comprador.
documentstringcondicionalpix: CPF (11 dígitos) ou CNPJ (14 dígitos) válido, só números. spei: RFC ou CURP do comprador. bizum: não é exigido.
phonestringopcionalFormato E.164, com + e código do país, ex.: +5511999999999. Precisa ser um número válido.
birthDatestringopcionalData de nascimento no formato DD/MM/AAAA, ex.: 15/01/1990. O formato AAAA-MM-DD é recusado.
addressobjetoopcionalEndereço no formato brasileiro (abaixo). Não envie no bizum nem no spei.
utmobjetoopcionalParâmetros de rastreamento da venda (abaixo).

Objeto customer.address

Se enviar o endereço, os campos marcados como obrigatórios passam a ser exigidos.

CampoTipoObrigatórioDescrição
zipCodestringobrigatórioCEP com 8 dígitos, sem hífen.
streetstringobrigatórioLogradouro, de 3 a 128 caracteres.
districtstringobrigatórioBairro, de 3 a 128 caracteres.
citystringobrigatórioCidade, de 3 a 128 caracteres.
statestringobrigatórioUF, ex.: SP.
numberstringopcionalNúmero, de 1 a 6 caracteres.
complementstringopcionalComplemento, de 1 a 48 caracteres.

Objeto customer.utm

CampoTipoDescrição
sourcestringutm_source, até 128 caracteres.
mediumstringutm_medium, até 128 caracteres.
campaignstringutm_campaign, até 128 caracteres.
termstringutm_term, até 128 caracteres.
contentstringutm_content, até 128 caracteres.
srcstringParâmetro src usado na integração com a Utmify, até 2048 caracteres.
sckstringParâmetro sck usado na integração com a Utmify, até 256 caracteres.

Exemplo completo

curl -X POST https://api.pagpayze.com.br/api/v1/direct-payments \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $PAYZE_API_KEY" \
  -d '{
    "amount": 15000,
    "description": "Assinatura anual",
    "paymentMethod": "pix",
    "customer": {
      "name": "Maria Souza",
      "email": "maria@exemplo.com",
      "document": "12345678909",
      "phone": "+5511999999999",
      "birthDate": "15/01/1990",
      "address": {
        "zipCode": "01310100",
        "street": "Avenida Paulista",
        "number": "1000",
        "complement": "Sala 101",
        "district": "Bela Vista",
        "city": "São Paulo",
        "state": "SP"
      },
      "utm": { "source": "google", "medium": "cpc", "campaign": "lancamento" }
    }
  }'
const res = await fetch("https://api.pagpayze.com.br/api/v1/direct-payments", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": process.env.PAYZE_API_KEY,
  },
  body: JSON.stringify({
    amount: 15000,
    description: "Assinatura anual",
    paymentMethod: "pix",
    customer: {
      name: "Maria Souza",
      email: "maria@exemplo.com",
      document: "12345678909",
      phone: "+5511999999999",
      birthDate: "15/01/1990",
      address: {
        zipCode: "01310100",
        street: "Avenida Paulista",
        number: "1000",
        complement: "Sala 101",
        district: "Bela Vista",
        city: "São Paulo",
        state: "SP",
      },
      utm: { source: "google", medium: "cpc", campaign: "lancamento" },
    },
  }),
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error} ${body.errorFields.join("; ")}`);
$payload = [
  "amount" => 15000,
  "description" => "Assinatura anual",
  "paymentMethod" => "pix",
  "customer" => [
    "name" => "Maria Souza",
    "email" => "maria@exemplo.com",
    "document" => "12345678909",
    "phone" => "+5511999999999",
    "birthDate" => "15/01/1990",
    "address" => [
      "zipCode" => "01310100",
      "street" => "Avenida Paulista",
      "number" => "1000",
      "complement" => "Sala 101",
      "district" => "Bela Vista",
      "city" => "São Paulo",
      "state" => "SP",
    ],
    "utm" => ["source" => "google", "medium" => "cpc", "campaign" => "lancamento"],
  ],
];

$ch = curl_init("https://api.pagpayze.com.br/api/v1/direct-payments");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Content-Type: application/json", "X-API-Key: " . getenv("PAYZE_API_KEY")],
  CURLOPT_POSTFIELDS => json_encode($payload),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);

Resposta

Com sucesso, a API responde 201 Created:

CampoTipoDescrição
transaction_idstringIdentificador da transação na Payze. Use na consulta de status e para reconhecer o webhook.
total_valuenúmeroValor cobrado em unidades da moeda da cobrança (não em centavos): reais no PIX, euros no Bizum, pesos no SPEI.
currencystringSó no bizum (EUR) e no spei (MXN).
statusstringStatus inicial da cobrança, normalmente PENDING.
emailstringE-mail do comprador, em minúsculas.
payment_methodstringO método enviado, em minúsculas (pix, bizum, spei).
payment_dataobjetoO que o comprador precisa para pagar. Muda por método: veja PIX, Bizum e SPEI.
Cada chamada cria uma cobrança nova

A criação não tem chave de idempotência. Se a requisição falhar por timeout ou erro de rede, não repita automaticamente: confira em Vendas, no painel, se a cobrança foi criada antes de gerar outra.

Erros mais comuns

HTTPMensagemO que fazer
401API key não fornecida… e similaresVeja Autenticação.
400Erro na validação dos camposLeia errorFields: ele lista cada campo com problema.
400document é obrigatório para este método de pagamentoEnvie o CPF ou CNPJ do comprador no PIX.
400document deve ser um CPF ou CNPJ válido (somente números)Confira os dígitos do documento.
400Você ainda não possui documentos validados para gerar pagamentosConclua a validação de documentos da sua conta no painel.

A lista completa está em Erros; os erros de cada método estão nas páginas do Bizum e do SPEI.

Métodos por país

Brasil · PIX

Cobrança em reais paga com copia-e-cola ou QR Code no app do banco.

País BR Moeda BRL paymentMethod "pix"

Requisição

CampoRegra no PIX
amountCentavos de real. 9990 = R$ 99,90.
customer.documentobrigatório CPF ou CNPJ válido, só números.
returnUrl, sourceUrlNão são usados.
curl -X POST https://api.pagpayze.com.br/api/v1/direct-payments \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $PAYZE_API_KEY" \
  -d '{
    "amount": 9990,
    "description": "Pedido 1234",
    "paymentMethod": "pix",
    "customer": { "name": "João da Silva", "email": "joao@exemplo.com", "document": "12345678909" }
  }'
const res = await fetch("https://api.pagpayze.com.br/api/v1/direct-payments", {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": process.env.PAYZE_API_KEY },
  body: JSON.stringify({
    amount: 9990,
    description: "Pedido 1234",
    paymentMethod: "pix",
    customer: { name: "João da Silva", email: "joao@exemplo.com", document: "12345678909" },
  }),
});
const { data } = await res.json();
// Para o front: só o copia-e-cola e o valor
return { transactionId: data.transaction_id, pix: data.payment_data.pix_key, valor: data.total_value };
$ch = curl_init("https://api.pagpayze.com.br/api/v1/direct-payments");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Content-Type: application/json", "X-API-Key: " . getenv("PAYZE_API_KEY")],
  CURLOPT_POSTFIELDS => json_encode([
    "amount" => 9990,
    "description" => "Pedido 1234",
    "paymentMethod" => "pix",
    "customer" => ["name" => "João da Silva", "email" => "joao@exemplo.com", "document" => "12345678909"],
  ]),
]);
$data = json_decode(curl_exec($ch), true)["data"];
curl_close($ch);
$copiaECola = $data["payment_data"]["pix_key"];

Resposta

Campos de payment_data no PIX:

CampoTipoDescrição
pix_keystringCódigo PIX copia-e-cola. Mostre com botão de copiar e gere o QR Code a partir dele.
expiration_datestring | nullValidade informada pelo processador, em ISO 8601. Pode vir null.
payment_idstringIdentificador da cobrança no processador. Para tudo na Payze, use o transaction_id.
status, status_detailstringSituação no momento da criação (PENDING / WAITING_PAYMENT). Não muda depois: o status que vale é o da raiz, na consulta ou no webhook.
total_transaction_valuenúmeroValor em reais.

Dependendo do processador, payment_data pode trazer outros campos. Ignore os que você não usa.

Tela de pagamento

  • Mostre o valor, o código copia-e-cola com botão Copiar e o QR Code gerado a partir de pix_key.
  • Enquanto a tela estiver aberta, consulte o status a cada 5 a 15 segundos para trocar a mensagem quando o pagamento for confirmado. A consulta não exige API Key e pode ser feita pelo navegador.
  • Essa consulta no navegador serve só para a experiência do comprador. A liberação do pedido acontece no seu servidor (webhook + consulta).
async function aguardarPagamento(transactionId, { intervalo = 10000, limite = 30 * 60 * 1000 } = {}) {
  const url = `https://api.pagpayze.com.br/api/v1/payments/${transactionId}/status`;
  const fim = Date.now() + limite;
  while (Date.now() < fim) {
    const res = await fetch(url);
    if (res.ok) {
      const { data } = await res.json();
      if (data.status === "AUTHORIZED") return "pago";
      if (["REJECTED", "CANCELED"].includes(data.status)) return "nao-pago";
    }
    await new Promise((r) => setTimeout(r, intervalo));
  }
  return "tempo-esgotado";
}

Vencimento

Não existe status de expiração

Um PIX vencido e não pago pode continuar PENDING ou mudar para REJECTED ou CANCELED, conforme o processador. Controle o prazo do pedido do seu lado e, se o comprador voltar depois, gere uma nova cobrança.

Métodos por país

Espanha · Bizum

Pagamento instantâneo espanhol, cobrado em euros. O formulário de pagamento é montado na sua página pelo SDK de checkout e o comprador aprova a cobrança no app do banco.

País ES Moeda EUR paymentMethod "bizum"

Como funciona

  1. Seu servidor cria a cobrança

    Com paymentMethod: "bizum" e um returnUrl. A resposta traz a sessão do formulário em payment_data.session.

  2. Sua página monta o formulário

    Carregue o script de session.sdk_url e chame CheckoutSDK.mount com a sessão.

  3. O comprador aprova no banco

    Ele preenche o formulário, confirma e aprova no app do banco. Nesse passo ele sai da sua página e depois volta para o seu returnUrl.

  4. Você confirma no servidor

    A página do returnUrl mostra “aguardando confirmação”. O pedido é liberado quando o webhook ou a consulta trouxerem AUTHORIZED.

Requisição

CampoRegra no Bizum
amountCentavos de euro. 1612 = 16,12 €. Mínimo 100 (1,00 €).
returnUrlobrigatório URL https de uma página sua.
sourceUrlopcional URL https do seu checkout. Recomendado.
customer.documentNão é exigido. Envie só nome e e-mail.
customer.phoneopcional E.164, ex.: +34612345678.
customer.addressNão envie (o formato é brasileiro).
curl -X POST https://api.pagpayze.com.br/api/v1/direct-payments \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $PAYZE_API_KEY" \
  -d '{
    "amount": 1612,
    "description": "Pedido 1234",
    "paymentMethod": "bizum",
    "returnUrl": "https://loja.exemplo.com/pedido/1234/aguardando",
    "sourceUrl": "https://loja.exemplo.com/checkout",
    "customer": { "name": "Ana García López", "email": "ana@exemplo.com" }
  }'
const res = await fetch("https://api.pagpayze.com.br/api/v1/direct-payments", {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": process.env.PAYZE_API_KEY },
  body: JSON.stringify({
    amount: Math.round(pedido.totalEur * 100), // euros → centavos
    description: `Pedido ${pedido.id}`,
    paymentMethod: "bizum",
    returnUrl: `https://loja.exemplo.com/pedido/${pedido.id}/aguardando`,
    sourceUrl: "https://loja.exemplo.com/checkout",
    customer: { name: pedido.nome, email: pedido.email },
  }),
});
const body = await res.json();
if (!res.ok) throw new Error(body.error);

await salvarTransacao(pedido.id, body.data.transaction_id);
// Para o front: só a sessão (e o valor, se for exibir)
return { session: body.data.payment_data.session, valor: body.data.total_value, moeda: body.data.currency };
$ch = curl_init("https://api.pagpayze.com.br/api/v1/direct-payments");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Content-Type: application/json", "X-API-Key: " . getenv("PAYZE_API_KEY")],
  CURLOPT_POSTFIELDS => json_encode([
    "amount" => 1612, // 16,12 € em centavos
    "description" => "Pedido 1234",
    "paymentMethod" => "bizum",
    "returnUrl" => "https://loja.exemplo.com/pedido/1234/aguardando",
    "sourceUrl" => "https://loja.exemplo.com/checkout",
    "customer" => ["name" => "Ana García López", "email" => "ana@exemplo.com"],
  ]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$session = $body["data"]["payment_data"]["session"]; // repasse ao front

Resposta

{
  "hasError": false,
  "data": {
    "transaction_id": "Q8W3E5R7T9Y2",
    "total_value": 16.12,
    "currency": "EUR",
    "status": "PENDING",
    "email": "ana@exemplo.com",
    "payment_method": "bizum",
    "payment_data": {
      "payment_id": "…",
      "status": "PENDING",
      "status_detail": "WAITING_PAYMENT",
      "total_transaction_value": 16.12,
      "currency": "EUR",
      "amount": 16.12,
      "exchange_rate": 6.2,
      "session": {
        "session_token": "…",
        "public_key": "…",
        "account": null,
        "transaction_id": "…",
        "sdk_url": "https://compra-segura.pagpayze.com.br/sdk/v1/checkout.js",
        "sandbox": false
      }
    }
  }
}
Campo de payment_dataDescrição
sessionSessão do formulário. Repasse o objeto inteiro, sem alterar, ao SDK de checkout. Pode ganhar campos novos com o tempo.
session.sdk_urlURL do script do SDK. Carregue sempre a URL que veio na sessão.
amount, total_transaction_valueValor em euros que o comprador paga.
currencyEUR.
exchange_rateQuantos reais vale 1 euro na conversão usada. Informativo: o comprador paga exatamente amount.
payment_idIdentificador no processador. Use o transaction_id para tudo na Payze.

Montar o formulário

Resumo do front. As opções completas estão em SDK de checkout.

<div id="pagamento-bizum"></div>
<!-- use a URL de session.sdk_url -->
<script src="https://compra-segura.pagpayze.com.br/sdk/v1/checkout.js"></script>
// session = payment_data.session, entregue pelo SEU servidor
CheckoutSDK.mount({
  container: "#pagamento-bizum",
  session,
  locale: "es",
  onSuccess: () => mostrarAguardando(), // não é confirmação de pagamento
  onError: (e) => console.warn(e.code, e.message),
}).catch((e) => mostrarErro(e.message));

Página do returnUrl

  • Mostre “aguardando confirmação do banco” e consulte o status a cada 5 a 15 segundos, com um limite de tempo.
  • A consulta de status também devolve payment_data.session: se o comprador voltar antes de pagar, você pode montar o formulário de novo com ela, sem criar outra cobrança.
  • Com AUTHORIZED, mostre a confirmação. Com REJECTED ou CANCELED, ofereça gerar uma nova cobrança.

Erros específicos

HTTPMensagemO que fazer
400returnUrl é obrigatório para pagamento via Bizum (em errorFields)Envie returnUrl.
400returnUrl deve ser uma URL https válida / sourceUrl deve ser uma URL https válida (em errorFields)Use URL completa com https://.
400Valor mínimo para pagamento via Bizum é € 1,00 (valor da cobrança: € 0,50)Cobre no mínimo amount: 100.
400Pagamento via Bizum não está habilitado nesta plataformaFale com o suporte.
400Taxa de Bizum não configurada no plano de taxas do vendedorSua conta ainda não está liberada para Bizum. Fale com o suporte.
400Cotação EUR não configurada no provedor de pagamento / Pagamento via Bizum indisponível para este produtoConfiguração pendente na plataforma. Fale com o suporte.
400Não foi possível gerar o pagamento. Tente novamente.O processador não gerou a cobrança. Tente de novo manualmente (cria uma nova transação).

Cobranças

SDK de checkout

Script da Payze que monta o formulário de pagamento do Bizum dentro da sua página, a partir da sessão devolvida pela API. Você fornece o container e a sessão; o SDK cuida do formulário e da confirmação.

Carregar o script

  • Use sempre a URL de payment_data.session.sdk_url. Não fixe a URL no seu código: a versão pode mudar.
  • O script cria o objeto global CheckoutSDK. Carregá-lo mais de uma vez não tem efeito.
  • Em aplicações SPA, injete o <script> uma vez e só chame mount depois que ele carregar.
<div id="pagamento"></div>
<script src="https://compra-segura.pagpayze.com.br/sdk/v1/checkout.js"></script>

Montar o formulário

const form = await CheckoutSDK.mount({
  container: "#pagamento",          // elemento ou seletor CSS
  session,                          // payment_data.session, como veio da API
  locale: "es",                     // "pt" | "es" | "en" | "auto"
  appearance: { accent: "#2E7CF6", radius: "8px", font: "inherit" },
  onReady: () => esconderCarregando(),
  onChange: ({ canConfirm, total }) => {},
  onSuccess: (r) => mostrarAguardando(), // tentativa aceita, NÃO é pagamento confirmado
  onError: (e) => console.warn(e.code, e.message),
});

// Ao sair da página ou desmontar o componente:
form.destroy();

Opções de mount

OpçãoTipoObrigatórioDescrição
containerelemento | stringobrigatórioElemento, ou seletor CSS, onde o formulário é desenhado. O conteúdo do elemento é substituído.
sessionobjetoobrigatóriopayment_data.session da resposta da API, sem alterações.
localestringopcionalpt, es, en ou auto. Padrão: auto (idioma do navegador).
buttonobjeto | falseopcional{ label: "Pagar" } troca o texto do botão. false esconde o botão: você chama form.confirm() no seu.
appearanceobjetoopcionalaccent: cor do botão e do destaque do formulário. radius: arredondamento (padrão 10px). font: fonte (padrão inherit).
onReadyfunçãoopcionalChamada quando o formulário está pronto para uso.
onChangefunçãoopcionalRecebe { canConfirm, total } quando o formulário muda. canConfirm diz se já dá para confirmar; total é o valor exibido, quando disponível.
onSuccessfunçãoopcionalChamada quando a confirmação é aceita sem sair da página. Recebe um objeto com transaction_id e sandbox. Não confirma o pagamento.
onErrorfunçãoopcionalRecebe { code, message } quando algo falha. O formulário já mostra a mensagem ao comprador; use para log ou para a sua interface.

Retorno de mount

mount devolve uma Promise que resolve com o controle do formulário:

MembroDescrição
confirm()Dispara a confirmação. Use com button: false. Devolve uma Promise.
destroy()Limpa o container. Chame ao sair da página ou desmontar o componente.
sandboxtrue quando a sessão é de teste.

A Promise é rejeitada, sem chamar onError, quando o container não existe (code: "container") ou a sessão está incompleta (code: "session"). Se o formulário não carregar, onError recebe code: "load" e a Promise também é rejeitada. Trate sempre o .catch.

Botão próprio

const botao = document.querySelector("#pagar");
botao.disabled = true;

const form = await CheckoutSDK.mount({
  container: "#pagamento",
  session,
  button: false,
  onChange: ({ canConfirm }) => { botao.disabled = !canConfirm; },
});

botao.addEventListener("click", () => form.confirm());

Exemplo em React

import { useEffect, useRef } from "react";

function carregarSdk(src) {
  return new Promise((resolve, reject) => {
    if (window.CheckoutSDK) return resolve(window.CheckoutSDK);
    const s = document.createElement("script");
    s.src = src;
    s.onload = () => resolve(window.CheckoutSDK);
    s.onerror = () => reject(new Error("Não foi possível carregar o formulário"));
    document.head.appendChild(s);
  });
}

export function FormularioBizum({ session, onAceito, onErro }) {
  const ref = useRef(null);

  useEffect(() => {
    let form;
    let cancelado = false;
    carregarSdk(session.sdk_url)
      .then((sdk) => {
        if (cancelado || !ref.current) return;
        return sdk.mount({
          container: ref.current,
          session,
          locale: "es",
          onSuccess: onAceito,
          onError: (e) => onErro?.(e.message),
        });
      })
      .then((f) => {
        form = f;
        if (cancelado) form?.destroy();
      })
      .catch((e) => onErro?.(e.message));

    return () => {
      cancelado = true;
      form?.destroy();
    };
  }, [session.session_token]);

  return <div ref={ref} />;
}

Depois da confirmação

  • No Bizum, o comprador normalmente sai da sua página para aprovar no banco e volta pelo returnUrl. Nesse caminho, onSuccess pode nem ser chamado. Quem mostra “aguardando confirmação” e consulta o status é a página do returnUrl.
  • onSuccess significa “tentativa aceita”. O pagamento só está confirmado quando a transação chega a AUTHORIZED (webhook ou consulta).

Sessão de teste

Se session.sandbox vier true, o SDK mostra um formulário simulado, com o botão “Simular pagamento” (no idioma do locale). Nada é cobrado e onSuccess recebe sandbox: true.

Content Security Policy

Se o seu site define CSP, libere estas origens
  • script-src: o domínio de session.sdk_url (https://compra-segura.pagpayze.com.br) e https://js.stripe.com
  • frame-src: https://js.stripe.com https://*.stripe.com
  • connect-src: https://api.stripe.com
  • style-src: o SDK injeta o próprio CSS numa tag <style>; permita estilos inline ('unsafe-inline') ou o hash correspondente.

Métodos por país

México · SPEI

Transferência bancária instantânea do México, cobrada em pesos mexicanos. A API devolve uma CLABE e o comprador transfere o valor exato pelo app do banco. Não há SDK nem redirecionamento.

País MX Moeda MXN paymentMethod "spei"

Requisição

CampoRegra no SPEI
amountCentavos de peso mexicano. 37400 = MX$ 374,00. Mínimo 100 (MX$ 1,00).
customer.documentobrigatório RFC (12 ou 13 caracteres) ou CURP (18 caracteres) do comprador. A API converte para maiúsculas e remove espaços, pontos e hífens. CPF e CNPJ são recusados.
sourceUrlopcional URL https do seu checkout. Recomendado.
returnUrlNão é usado.
customer.phoneopcional E.164, ex.: +525512345678.
customer.addressNão envie (o formato é brasileiro).
curl -X POST https://api.pagpayze.com.br/api/v1/direct-payments \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $PAYZE_API_KEY" \
  -d '{
    "amount": 37400,
    "description": "Pedido 1234",
    "paymentMethod": "spei",
    "sourceUrl": "https://loja.exemplo.com/checkout",
    "customer": {
      "name": "Sofía Hernández López",
      "email": "sofia@exemplo.com",
      "document": "HEGS900101MDFRRF09"
    }
  }'
const res = await fetch("https://api.pagpayze.com.br/api/v1/direct-payments", {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": process.env.PAYZE_API_KEY },
  body: JSON.stringify({
    amount: Math.round(pedido.totalMxn * 100), // pesos → centavos
    description: `Pedido ${pedido.id}`,
    paymentMethod: "spei",
    sourceUrl: "https://loja.exemplo.com/checkout",
    customer: {
      name: pedido.nome,
      email: pedido.email,
      document: pedido.curpOuRfc.toUpperCase().replace(/[\s.-]/g, ""),
    },
  }),
});
const body = await res.json();
if (!res.ok) throw new Error(body.error);

await salvarTransacao(pedido.id, body.data.transaction_id);
return { spei: body.data.payment_data.spei, valor: body.data.total_value, moeda: body.data.currency };
$ch = curl_init("https://api.pagpayze.com.br/api/v1/direct-payments");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Content-Type: application/json", "X-API-Key: " . getenv("PAYZE_API_KEY")],
  CURLOPT_POSTFIELDS => json_encode([
    "amount" => 37400, // MX$ 374,00 em centavos
    "description" => "Pedido 1234",
    "paymentMethod" => "spei",
    "sourceUrl" => "https://loja.exemplo.com/checkout",
    "customer" => [
      "name" => "Sofía Hernández López",
      "email" => "sofia@exemplo.com",
      "document" => "HEGS900101MDFRRF09",
    ],
  ]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$spei = $body["data"]["payment_data"]["spei"]; // CLABE e validade para o front

Resposta

{
  "hasError": false,
  "data": {
    "transaction_id": "M4X8C2V6B0N3",
    "total_value": 374,
    "currency": "MXN",
    "status": "PENDING",
    "email": "sofia@exemplo.com",
    "payment_method": "spei",
    "payment_data": {
      "payment_id": "…",
      "status": "PENDING",
      "status_detail": "WAITING_PAYMENT",
      "total_transaction_value": 374,
      "currency": "MXN",
      "amount": 374,
      "exchange_rate": 0.3,
      "spei": {
        "clabe": "012180001234567890",
        "reference": "1234567",
        "bank": null,
        "beneficiary": null,
        "expires_at": "2026-10-09T05:59:00.000Z"
      }
    }
  }
}
Campo de payment_data.speiTipoDescrição
clabestringCLABE de 18 dígitos para onde o comprador transfere. Sempre presente.
referencestring | nullReferência da transferência, quando houver.
bankstring | nullBanco de destino, quando informado.
beneficiarystring | nullBeneficiário, quando informado.
expires_atstring | nullValidade da CLABE em ISO 8601 (UTC).

Em payment_data também vêm currency (MXN), amount (valor em pesos) e exchange_rate (quantos reais vale 1 peso na conversão usada; informativo).

Tela de pagamento

  • Valor em pesos, CLABE em fonte monoespaçada com botão Copiar, referência (se houver) e validade no fuso da Cidade do México.
  • Instrua o comprador a transferir o valor exato pelo app do banco, escolhendo transferência SPEI.
  • Se a página recarregar, recupere payment_data.spei pela consulta de status. Não crie outra cobrança.
  • Depois de expires_at, ofereça gerar uma nova cobrança.
// spei, valor: dados que o seu servidor repassou da resposta da API
const valorFormatado = new Intl.NumberFormat("es-MX", { style: "currency", currency: "MXN" }).format(valor);
const validade = spei.expires_at
  ? new Intl.DateTimeFormat("es-MX", {
      dateStyle: "short",
      timeStyle: "short",
      timeZone: "America/Mexico_City",
    }).format(new Date(spei.expires_at))
  : null;

document.querySelector("#clabe").textContent = spei.clabe;
document.querySelector("#copiar-clabe").addEventListener("click", () => navigator.clipboard.writeText(spei.clabe));

Validar o RFC ou o CURP no formulário

A API usa as mesmas regras abaixo. Validar antes evita uma ida e volta.

function documentoMexicoValido(valor) {
  const doc = valor.toUpperCase().replace(/[\s.-]/g, "");
  const RFC = /^[A-ZÑ&]{3,4}\d{6}[A-Z\d]{3}$/;
  const CURP = /^[A-Z][AEIOUX][A-Z]{2}\d{6}[HMX][A-Z]{2}[B-DF-HJ-NP-TV-Z]{3}[A-Z\d]\d$/;
  return RFC.test(doc) || CURP.test(doc);
}

Erros específicos

HTTPMensagemO que fazer
400document (RFC ou CURP do comprador) é obrigatório para pagamento via SPEIEnvie customer.document.
400document deve ser um RFC ou CURP válido para pagamento via SPEIConfira o documento. CPF e CNPJ não valem no SPEI.
400document deve ser um CPF/CNPJ válido (somente números) ou, no SPEI, um RFC/CURP válido (em errorFields)O valor enviado não é nenhum documento aceito.
400Valor mínimo para pagamento via SPEI é MX$ 1,00 (valor da cobrança: MX$ 0,50)Cobre no mínimo amount: 100.
400sourceUrl deve ser uma URL https válida (em errorFields)Use URL completa com https://.
400Pagamento via SPEI não está habilitado nesta plataformaFale com o suporte.
400Taxa de SPEI não configurada no plano de taxas do vendedorSua conta ainda não está liberada para SPEI. Fale com o suporte.
400Cotação MXN não configurada no provedor de pagamento / Pagamento via SPEI indisponível para este produtoConfiguração pendente na plataforma. Fale com o suporte.
400Não foi possível gerar o pagamento. Tente novamente.O processador não gerou a cobrança. Tente de novo manualmente (cria uma nova transação).

Depois do pagamento

Consultar status

GET/api/v1/payments/{transaction_id}/statusSem autenticação

Devolve o status atual da transação e os dados de pagamento gravados na criação. Não exige API Key: pode ser chamada pelo seu servidor, para confirmar um webhook, e pelo navegador, para atualizar a tela do comprador.

Parâmetro

ParâmetroEmDescrição
transaction_idcaminhoO transaction_id devolvido na criação da cobrança.

Requisição

curl https://api.pagpayze.com.br/api/v1/payments/7KQ2M9XA4T1B/status
const res = await fetch(`https://api.pagpayze.com.br/api/v1/payments/${transactionId}/status`);
const body = await res.json();
if (!res.ok) throw new Error(body.error); // ex.: "Pedido não encontrado!"

console.log(body.data.status); // "PENDING", "AUTHORIZED"…
$url = "https://api.pagpayze.com.br/api/v1/payments/" . urlencode($transactionId) . "/status";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);

$status = $body["data"]["status"] ?? null; // "PENDING", "AUTHORIZED"…

Resposta

{
  "hasError": false,
  "data": {
    "transaction_id": "7KQ2M9XA4T1B",
    "total_value": 99.9,
    "fee": 4.49,
    "net_value": 95.41,
    "status": "AUTHORIZED",
    "product": null,
    "payment_method": "PIX",
    "producer": null,
    "payment_data": {
      "pix_key": "00020126580014br.gov.bcb.pix0136…6304A1B2",
      "expiration_date": null,
      "payment_id": "c1a7e0b2-5d3f-4e8a-9b61-0f2d7c4e9a13",
      "status": "PENDING",
      "status_detail": "WAITING_PAYMENT",
      "total_transaction_value": 99.9
    }
  }
}
{
  "hasError": false,
  "data": {
    "transaction_id": "Q8W3E5R7T9Y2",
    "total_value": 99.94,
    "fee": 5.99,
    "net_value": 93.95,
    "status": "PENDING",
    "product": null,
    "payment_method": "BIZUM",
    "producer": null,
    "payment_data": {
      "international": {
        "method": "BIZUM",
        "currency": "EUR",
        "amount": 16.12,
        "brl_amount": 99.94,
        "brl_per_unit": 6.2
      },
      "session": {
        "session_token": "…",
        "public_key": "…",
        "account": null,
        "transaction_id": "…",
        "sdk_url": "https://compra-segura.pagpayze.com.br/sdk/v1/checkout.js",
        "sandbox": false
      }
    }
  }
}
{
  "hasError": false,
  "data": {
    "transaction_id": "M4X8C2V6B0N3",
    "total_value": 112.2,
    "fee": 6.72,
    "net_value": 105.48,
    "status": "PENDING",
    "product": null,
    "payment_method": "SPEI",
    "producer": null,
    "payment_data": {
      "international": {
        "method": "SPEI",
        "currency": "MXN",
        "amount": 374,
        "brl_amount": 112.2,
        "brl_per_unit": 0.3
      },
      "spei": {
        "clabe": "012180001234567890",
        "reference": "1234567",
        "bank": null,
        "beneficiary": null,
        "expires_at": "2026-10-09T05:59:00.000Z"
      }
    }
  }
}
CampoTipoDescrição
transaction_idstringIdentificador da transação.
statusstringStatus atual. É o campo que vale; veja Status da transação.
total_valuenúmeroValor da transação em reais, também no Bizum e no SPEI.
feenúmeroTaxa da Payze, em reais.
net_valuenúmeroValor líquido para você, em reais.
payment_methodstringMétodo em maiúsculas: PIX, BIZUM, SPEI.
product, producerobjeto | nullnull nas cobranças criadas pela API. Vêm preenchidos nas vendas de produto feitas pelo checkout da Payze.
payment_dataobjetoDados gravados na criação: pix_key no PIX, session no Bizum, spei no SPEI.
payment_data.internationalobjetoSó no Bizum e no SPEI: currency e amount cobrados do comprador, brl_amount (valor convertido em reais) e brl_per_unit (cotação usada).
Use o status da raiz

No PIX, payment_data.status é a foto do momento da criação e continua PENDING mesmo depois do pagamento. O status atual é sempre data.status.

Moedas diferentes na criação e na consulta

A resposta da criação mostra o valor na moeda da cobrança (EUR ou MXN). A consulta e o webhook mostram total_value, fee e net_value em reais. Não exiba ao comprador os valores da consulta como se fossem euros ou pesos: o valor cobrado está em payment_data.international.amount.

Erros

HTTPMensagemCausa
400Pedido não encontrado!Não existe transação com esse transaction_id.

Polling

  • Consulte a cada 5 a 15 segundos, com um limite de tempo, e pare quando o status deixar de ser PENDING.
  • Polling é apoio. Para liberar pedidos, use o webhook e confirme com esta consulta.

Depois do pagamento

Webhooks

A Payze avisa o seu servidor com um POST em JSON quando uma transação sua é atualizada. Use o aviso como gatilho e confirme o status na consulta antes de liberar o pedido.

Cadastrar a URL

  1. No painel da Payze, abra Integração → Webhooks e clique em Novo Webhook.
  2. Informe um nome e a URL de destino. Use HTTPS.
  3. Clique em Cadastrar. O webhook já nasce ativo.
  • Você pode cadastrar mais de uma URL (o painel aceita até 10). Cada URL ativa recebe todos os avisos.
  • Em Editar, dá para pausar: webhooks pausados não recebem disparos.
  • Os avisos cobrem todas as transações da sua conta, não só as criadas pela API. Ignore os transaction_id que a sua integração não conhece.

Quando a Payze envia

  • Quando o processador informa uma atualização da transação: pagamento aprovado, recusa, cancelamento, estorno, chargeback, disputa e atualizações de pendência.
  • Quando a equipe da Payze aprova uma transação manualmente.
  • Não há aviso na criação da cobrança. Uma falha ao gerar a cobrança (FAILED) também não gera aviso: nesse caso a própria criação já respondeu erro.
  • O mesmo status pode chegar mais de uma vez, por exemplo duas atualizações seguidas com PENDING.

Requisição enviada

POST para a sua URL, com Content-Type: application/json e este corpo:

{
  "transaction_id": "7KQ2M9XA4T1B",
  "total_value": 99.9,
  "fee": 4.49,
  "net_value": 95.41,
  "status": "AUTHORIZED",
  "product": null,
  "payment_method": "PIX",
  "producer": null,
  "payment_data": {
    "pix_key": "00020126580014br.gov.bcb.pix0136…6304A1B2",
    "expiration_date": null,
    "payment_id": "c1a7e0b2-5d3f-4e8a-9b61-0f2d7c4e9a13",
    "status": "PENDING",
    "status_detail": "WAITING_PAYMENT",
    "total_transaction_value": 99.9
  },
  "customer": {
    "name": "João da Silva",
    "email": "joao@exemplo.com",
    "document": "12345678909",
    "phone": "+5511999999999",
    "birth_date": "15/01/1990",
    "address": {}
  }
}
CampoDescrição
transaction_idA transação atualizada. Localize o seu pedido por ele.
statusStatus atual da transação. Não há campo de nome de evento: o que importa é o status.
total_value, fee, net_valueValor, taxa e líquido em reais.
payment_methodEm maiúsculas: PIX, BIZUM, SPEI.
product, producernull nas cobranças da API; preenchidos nas vendas de produto do checkout da Payze.
payment_dataO mesmo objeto da consulta de status.
customerComprador: name, email, document, phone, birth_date e address (com as chaves cep, street, number, complement, neighborhood, city e state; vazio se não foi enviado).

Entrega e retentativas

  • Responda com HTTP 2xx. Qualquer outro status, ou erro de rede, conta como falha.
  • São até 3 tentativas no total, com 15 segundos entre elas. Depois da terceira falha, aquele aviso não é reenviado: recupere o estado pela consulta de status.
  • Responda rápido: grave o aviso, devolva 200 e processe em segundo plano.
  • A ordem de chegada não é garantida. Por isso, confirme o status atual na consulta antes de agir.

Segurança

Os avisos não são assinados

Trate o corpo do webhook como um aviso, não como prova de pagamento. Antes de liberar o pedido, confirme com GET /api/v1/payments/{transaction_id}/status. Use HTTPS e uma URL difícil de adivinhar, por exemplo com um token secreto no caminho, e confira esse token ao receber.

Idempotência

  • O mesmo aviso pode chegar mais de uma vez (retentativas e atualizações repetidas). Liberar o pedido duas vezes precisa ser impossível.
  • Uma transação aprovada pode mudar depois para REFUNDED, CHARGEBACK ou IN_DISPUTE. Não descarte um aviso só porque já viu aquele transaction_id: deduplique por transaction_id + status.
  • Torne a liberação atômica: marque o pedido como pago numa atualização condicional (por exemplo, UPDATE … WHERE status <> 'pago') e entregue só se a atualização mudou uma linha.

Exemplo de receptor

import express from "express";

const app = express();
app.use(express.json());

const API = "https://api.pagpayze.com.br/api/v1";

app.post("/webhooks/payze/:token", async (req, res) => {
  if (req.params.token !== process.env.PAYZE_WEBHOOK_TOKEN) return res.sendStatus(404);
  res.sendStatus(200); // responda logo; processe em seguida

  const transactionId = req.body?.transaction_id;
  if (!transactionId) return;

  const pedido = await db.pedidos.porTransacao(transactionId);
  if (!pedido) return; // transação que não é desta integração

  // Confirma o status na fonte antes de agir
  const r = await fetch(`${API}/payments/${transactionId}/status`);
  if (!r.ok) return;
  const { data } = await r.json();

  if (data.status === "AUTHORIZED") {
    const mudou = await db.pedidos.marcarPagoSeAindaNao(pedido.id); // UPDATE condicional
    if (mudou) await liberarPedido(pedido);
  } else if (["REFUNDED", "CHARGEBACK"].includes(data.status)) {
    await revogarPedido(pedido);
  }
});

app.listen(3000);
<?php
// URL cadastrada: https://loja.exemplo.com/webhook-payze.php?token=SEU_TOKEN
if (!hash_equals(getenv("PAYZE_WEBHOOK_TOKEN"), $_GET["token"] ?? "")) {
  http_response_code(404);
  exit;
}

$aviso = json_decode(file_get_contents("php://input"), true);
http_response_code(200);
$transactionId = $aviso["transaction_id"] ?? null;
if (!$transactionId) exit;

// Confirma o status na fonte antes de agir
$ch = curl_init("https://api.pagpayze.com.br/api/v1/payments/" . urlencode($transactionId) . "/status");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$status = json_decode(curl_exec($ch), true)["data"]["status"] ?? null;
curl_close($ch);

if ($status === "AUTHORIZED") {
  // UPDATE pedidos SET status = 'pago' WHERE transaction_id = ? AND status <> 'pago'
  // Se mudou 1 linha, libere o pedido.
}

Depois do pagamento

Status da transação

O campo status da consulta e do webhook diz em que ponto a transação está. A venda está paga só com AUTHORIZED.

Ciclo de vida

PENDING→AUTHORIZED→REFUNDED·CHARGEBACK·IN_DISPUTE PENDING→REJECTED·CANCELED

Tabela de status

StatusSignificadoO que fazerWebhook
PENDINGCobrança criada, aguardando o pagamento.Mostrar os dados de pagamento e aguardar.sim
AUTHORIZEDPago.Liberar o pedido, uma única vez.sim
REJECTEDRecusado.Oferecer uma nova tentativa (nova cobrança).sim
CANCELEDCancelado.Encerrar o pedido ou gerar nova cobrança.sim
REFUNDEDValor devolvido ao comprador.Revogar acesso ou entrega.sim
CHARGEBACKPagamento contestado pelo comprador.Revogar acesso ou entrega.sim
IN_DISPUTEDisputa aberta, em análise.Suspender a entrega e acompanhar.sim
FAILEDO processador não gerou a cobrança.A criação já respondeu erro; corrija e tente de novo.não
DISPUTE_ACCEPTEDDisputa encerrada com devolução ao comprador.Revogar acesso ou entrega.não
DISPUTE_REJECTEDDisputa encerrada a favor da venda.A venda segue válida.não

Os status sem webhook só aparecem na consulta de status e no painel.

Não existe status de expiração

Uma cobrança vencida e não paga pode continuar PENDING ou passar para REJECTED ou CANCELED, conforme o processador. Controle o prazo do pedido do seu lado.

AUTHORIZED pode mudar

Depois de pago, um pedido ainda pode virar REFUNDED, CHARGEBACK ou IN_DISPUTE. Mantenha o webhook tratando esses status mesmo para pedidos já entregues.

Referência

Erros

Erros respondem com hasError: true, o código HTTP em statusCode e a mensagem em error. Erros de validação listam cada problema em errorFields.

Formato

{
  "hasError": true,
  "error": "Erro na validação dos campos",
  "errorFields": [
    "amount must not be less than 1",
    "customer.email must be an email"
  ],
  "statusCode": 400,
  "timestamp": "2026-10-08T15:19:00.782Z",
  "path": "/api/v1/direct-payments"
}
CampoDescrição
hasErrorSempre true em erro.
errorMensagem principal. Nos erros de validação, é Erro na validação dos campos.
errorFieldsLista de problemas de validação, cada um citando o campo (ex.: customer.email). Vazia nos demais erros. As mensagens padrão de validação vêm em inglês.
statusCodeO mesmo código HTTP da resposta.
timestamp, pathMomento (ISO 8601, UTC) e caminho da requisição. Úteis ao falar com o suporte.

Códigos HTTP

HTTPQuando
200Consulta de status com sucesso.
201Cobrança criada.
400Dados inválidos ou regra de negócio: validação, documento, valor mínimo, método indisponível, recusa do processador. Também quando a transação consultada não existe.
401API Key ausente, inválida ou pausada, ou conta bloqueada.
404Rota inexistente. Confira o método HTTP e o caminho.
429Muitas requisições em pouco tempo. Espere alguns segundos e tente de novo.
500Erro inesperado. Tente de novo; se persistir, fale com o suporte informando timestamp e path.

Mensagens comuns

Autenticação · 401

MensagemCausa
API key não fornecida. Envie a chave no header X-API-KeyHeader ausente.
Formato de API key inválidoValor fora do formato pk_live_ + 48 hexadecimais.
API key inválidaChave inexistente ou deletada.
API key está inativa ou revogadaChave pausada.
Seller está bloqueado para receber pagamentosConta bloqueada.

Validação · 400, em errorFields

MensagemCausa
property currency should not existCampo desconhecido no corpo (aqui, currency).
returnUrl é obrigatório para pagamento via BizumBizum sem returnUrl.
returnUrl deve ser uma URL https válidaURL sem https:// ou malformada.
sourceUrl deve ser uma URL https válidaURL sem https:// ou malformada.
document deve ser um CPF/CNPJ válido (somente números) ou, no SPEI, um RFC/CURP válidoO documento não é nenhum dos aceitos.
A data de nascimento deve ser válida e estar no formato DD/MM/YYYYbirthDate fora do formato.

Regras de negócio · 400, em error

MensagemCausa
document é obrigatório para este método de pagamentoPIX sem CPF/CNPJ.
document deve ser um CPF ou CNPJ válido (somente números)PIX com documento inválido.
document (RFC ou CURP do comprador) é obrigatório para pagamento via SPEISPEI sem documento.
document deve ser um RFC ou CURP válido para pagamento via SPEISPEI com documento inválido.
Valor mínimo para pagamento via Bizum é € 1,00 (…) / … via SPEI é MX$ 1,00 (…)amount abaixo de 100 no Bizum ou no SPEI.
Pagamento via Bizum não está habilitado nesta plataforma (ou SPEI)Método desligado. Fale com o suporte.
Taxa de Bizum não configurada no plano de taxas do vendedor (ou SPEI)Método não liberado na sua conta. Fale com o suporte.
Cotação EUR não configurada no provedor de pagamento (ou MXN)Configuração pendente. Fale com o suporte.
Pagamento via Bizum indisponível para este produto (ou SPEI)Configuração pendente. Fale com o suporte.
Você ainda não possui documentos validados para gerar pagamentosValidação de documentos da conta pendente.
Não foi possível gerar o pagamento. Tente novamente.Bizum ou SPEI: o processador não gerou a cobrança. A transação fica FAILED.
Mensagem variávelPIX: o processador não gerou a cobrança. A transação fica FAILED.
Pedido não encontrado!Consulta de status com transaction_id inexistente.

Como tratar

  • 400 de validação ou regra: corrija a requisição. Repetir igual dá o mesmo erro.
  • Recusa do processador: pode tentar de novo, manualmente. Cada tentativa cria uma nova transação.
  • 429, 500 e timeouts: espere e tente de novo com intervalo crescente. Antes de recriar uma cobrança, confira no painel se a anterior não foi criada.

Referência

Valores e limites

Unidades de valor, mínimos por método, formatos de dados e limites da conta.

Unidades de valor

OndeUnidadeExemplo
amount na criaçãoInteiro, em centavos da moeda da cobrança9990 = R$ 99,90 · 1612 = 16,12 € · 37400 = MX$ 374,00
total_value na resposta da criaçãoDecimal, na moeda da cobrança99.9 · 16.12 · 374
total_value, fee, net_value na consulta e no webhookDecimal, sempre em reais99.9
payment_data.international.amountDecimal, na moeda da cobrança16.12
Conversão para reais

No Bizum e no SPEI, o comprador paga exatamente o amount enviado, na moeda dele. A Payze converte esse valor para reais pela cotação cadastrada na plataforma (exchange_rate na criação, brl_per_unit na consulta), e taxas, splits e saldo são calculados em BRL.

Valores mínimos

MétodoMínimo de amountEquivale a
pix1R$ 0,01 (limite da validação da API)
bizum1001,00 €
spei100MX$ 1,00

Tamanho dos campos

CampoLimite
description3 a 255 caracteres
customer.name3 a 128 caracteres
returnUrl, sourceUrlhttps, até 2048 caracteres
customer.utm.*até 128 caracteres; src até 2048 e sck até 256
customer.address.*veja Criar cobrança

Formatos

DadoFormatoExemplo
CPF / CNPJSó números, 11 ou 14 dígitos, dígitos verificadores válidos12345678909
RFC / CURPMaiúsculas, sem espaços, pontos ou hífensHEGS900101MDFRRF09
TelefoneE.164+5511999999999
Data de nascimentoDD/MM/AAAA15/01/1990
CEP8 dígitos, sem hífen01310100
Datas nas respostasISO 8601, UTC2026-10-08T15:19:00.782Z

Limites da conta

  • API Keys: até 10 ativas por conta.
  • Webhooks: o painel aceita até 10 URLs.
  • Requisições: a API limita o volume de chamadas em sequência e responde 429 quando o limite é atingido. Faça polling a cada 5 a 15 segundos, nunca em laço contínuo.

Referência

Checklist de produção

Confira estes pontos antes de colocar a integração no ar.

Geral

  • A API Key fica só no servidor, em variável de ambiente ou cofre de segredos. Nunca no front nem no repositório.
  • amount é inteiro, em centavos da moeda do método.
  • O transaction_id é salvo no pedido logo após a criação.
  • A criação não é repetida automaticamente em erro ou timeout.
  • O webhook está cadastrado com HTTPS e responde 2xx rápido.
  • Antes de liberar o pedido, o servidor confirma AUTHORIZED na consulta de status, e a liberação é idempotente.
  • REFUNDED, CHARGEBACK e IN_DISPUTE são tratados também em pedidos já entregues.
  • Valores da consulta e do webhook (em reais) não são exibidos ao comprador como se fossem euros ou pesos.

PIX

  • Copia-e-cola com botão de copiar e QR Code gerado de pix_key.
  • O prazo do pedido é controlado do seu lado; depois dele, uma nova cobrança é gerada.

Bizum

  • returnUrl https aponta para uma página que mostra “aguardando confirmação” e consulta o status.
  • O SDK é carregado de session.sdk_url, o .catch de mount é tratado e destroy() é chamado ao sair.
  • onSuccess só mostra “aguardando”; nada é liberado por ele.
  • A CSP do site libera as origens listadas no SDK de checkout.

SPEI

  • O formulário pede e valida RFC ou CURP; não pede CPF nem endereço brasileiro.
  • A CLABE aparece copiável, com valor em pesos e validade no fuso da Cidade do México.
  • Ao recarregar, a página usa os dados da consulta de status; depois de expires_at, gera uma nova cobrança.