Início rápido
Crie uma chave no painel, gere a primeira cobrança PIX e receba o webhook de pagamento.
Crie uma chave de API
No painel, abra Desenvolvedor › Credenciais e clique em Nova chave. Marque só as permissões que a integração usa e dê um nome que diga onde ela vai rodar, como “Checkout produção”.
O segredo começa com mxp_live_ e aparece uma única vez. Guarde no cofre de segredos ou numa variável de ambiente do seu servidor.
export MAXXIPAY_API_KEY="mxp_live_…"Crie a primeira cobrança
Envie o valor em centavos, uma descrição e os dados de quem paga. O cabeçalho Idempotency-Key garante que uma nova tentativa não crie uma segunda cobrança: use o identificador do pedido no seu sistema.
O campo externalId é opcional e guarda o seu identificador junto da cobrança, para conciliar depois e filtrar listas.
Exemplo de retorno, pelo contrato da rota. Não cria cobrança nem saque.
const response = await fetch("https://api.maxxipay.com/v1/charges", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MAXXIPAY_API_KEY}`,
"Idempotency-Key": "pedido-1042",
"Content-Type": "application/json",
},
body: JSON.stringify({
amountCents: 4990,
description: "Pedido 1042",
payerName: "Cliente Exemplo",
payerDocument: "529.982.247-25",
externalId: "pedido-1042",
metadata: {
canal: "checkout"
}
}),
});
const charge = await response.json();{
"id": "6f0c1a52-1d7e-4b8a-9f43-2c5e8d9b7a10",
"object": "charge",
"status": "pending",
"amountCents": 4990,
"feeCents": null,
"netCents": null,
"currency": "BRL",
"description": "Pedido 1042",
"payerName": "Cliente Exemplo",
"payerDocument": "52998224725",
"pixCopyPaste": "00020101021226870014br.gov.bcb.pix2565pix.exemplo.com.br/qr/v2/6f0c1a521d7e4b8a9f432c5e8d9b7a1052040000530398654044.905802BR6304B7C1",
"pixQrCode": "iVBORw0KGgoAAAANSUhEUgAA…",
"endToEndId": null,
"externalId": "pedido-1042",
"metadata": {
"canal": "checkout"
},
"failureReason": null,
"expiresAt": "2026-11-02T19:12:00.000Z",
"paidAt": null,
"createdAt": "2026-11-02T18:12:00.000Z",
"updatedAt": "2026-11-02T18:12:00.000Z"
}Mostre o PIX ao pagador
A resposta traz pixCopyPaste, o código PIX copia e cola, e pixQrCode, o PNG desse código em base64. Mostre o texto com um botão de copiar e a imagem direto em <img src="data:image/png;base64,...">.
A cobrança vale por 1 hora. O horário limite vem em expiresAt: depois dele o código não aceita pagamento.
const src = `data:image/png;base64,${charge.pixQrCode}`;
const html = `<img src="${src}" alt="QR Code PIX">`;Receba o webhook
Em Desenvolvedor › Webhooks, clique em Novo endpoint, informe a URL https e escolha os eventos. O painel mostra um segredo whsec_ uma única vez: ele assina cada entrega.
Quando o pagador paga, a MaxxiPay envia charge.paid com a cobrança completa. Confira a assinatura do corpo bruto, responda 2xx em até 5 segundos e processe depois.
{
"id": "charge.paid:6f0c1a52-1d7e-4b8a-9f43-2c5e8d9b7a10",
"type": "charge.paid",
"createdAt": "2026-11-02T18:13:41.000Z",
"data": {
"id": "6f0c1a52-1d7e-4b8a-9f43-2c5e8d9b7a10",
"object": "charge",
"status": "paid",
"amountCents": 4990,
"feeCents": 99,
"netCents": 4891,
"currency": "BRL",
"description": "Pedido 1042",
"payerName": "Cliente Exemplo",
"payerDocument": "52998224725",
"pixCopyPaste": "00020101021226870014br.gov.bcb.pix2565pix.exemplo.com.br/qr/v2/6f0c1a521d7e4b8a9f432c5e8d9b7a1052040000530398654044.905802BR6304B7C1",
"pixQrCode": "iVBORw0KGgoAAAANSUhEUgAA…",
"endToEndId": "E18236120202611021813s0a1b2c3d4e",
"externalId": "pedido-1042",
"metadata": {
"canal": "checkout"
},
"failureReason": null,
"expiresAt": "2026-11-02T19:12:00.000Z",
"paidAt": "2026-11-02T18:13:41.000Z",
"createdAt": "2026-11-02T18:12:00.000Z",
"updatedAt": "2026-11-02T18:13:41.000Z"
}
}import crypto from "node:crypto";
import express from "express";
const app = express();
const secret = process.env.MAXXIPAY_WEBHOOK_SECRET;
function isValid(rawBody, timestamp, header) {
const age = Math.abs(Date.now() / 1000 - Number(timestamp));
if (!Number.isFinite(age) || age > 300) return false;
const signed = Buffer.concat([Buffer.from(timestamp + "."), rawBody]);
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(signed).digest("hex");
const received = Buffer.from(header ?? "");
const wanted = Buffer.from(expected);
return received.length === wanted.length && crypto.timingSafeEqual(received, wanted);
}
app.post("/webhooks/maxxipay", express.raw({ type: "application/json" }), async (req, res) => {
if (!isValid(req.body, req.get("x-maxxipay-timestamp") ?? "", req.get("x-maxxipay-signature"))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString("utf8"));
res.sendStatus(200);
await processEvent(event);
});Confira o pagamento
Com o webhook processado, a cobrança está paid, com feeCents, netCents e o endToEndId da transação. O valor líquido já entra no saldo disponível.
Próximos passos: veja os status possíveis, as boas práticas de webhook e como sacar o saldo.
const response = await fetch("https://api.maxxipay.com/v1/charges/6f0c1a52-1d7e-4b8a-9f43-2c5e8d9b7a10", {
headers: {
Authorization: `Bearer ${process.env.MAXXIPAY_API_KEY}`,
},
});
const charge = await response.json();