Automatize sua operação com a API e os webhooks da Mitzpay
A Mitzpay processa seu checkout (Pix, cartão, boleto, PayPal e Solana) e avisa seus sistemas em tempo real. Esta página documenta tudo o que existe hoje na plataforma para integração: a API de consulta de pedidos e os webhooks assinados.
Endereço base da API:
https://mitzpay.com/api/v1
GET /api/v1/eu com ela. Se voltar o nome da sua conta, está tudo ligado.
Autenticação
Toda chamada à API leva a sua chave no cabeçalho Authorization, no formato
Bearer. A chave identifica a sua conta: você enxerga sempre, e somente, os seus próprios dados.
curl https://mitzpay.com/api/v1/eu \
-H "Authorization: Bearer mitz_SUA_CHAVE_AQUI"
- A chave aparece uma única vez, na criação. Guarde num cofre de segredos: no nosso banco fica só uma impressão digital dela.
- Nunca use a chave em código que roda no navegador: ela é de servidor para servidor.
- Vazou? Revogue na mesma tela e gere outra. A revogação vale na hora.
Códigos de resposta
| Código | Significado |
|---|---|
200 | Deu certo. O corpo traz o resultado em JSON. |
400 | Parâmetro inválido. O corpo diz qual, em { "erro": "..." }. |
401 | Chave ausente, inválida ou revogada. |
404 | O recurso não existe, ou não é seu (a API não diferencia, de propósito). |
429 | Limite de requisições atingido. Aguarde e tente de novo. |
500 | Erro nosso. Tente de novo; se persistir, fale com o suporte. |
Limites de uso
90 requisições por minuto por endereço IP e
120 por minuto por chave. As respostas trazem os cabeçalhos padrão
RateLimit-* com o saldo da janela. Ao receber 429, espere
o tempo indicado e reduza o ritmo. Para acompanhar vendas em tempo real, prefira
webhooks em vez de consultar a API em loop.
GET /api/v1/eu
Diz qual conta a chave abre. É o teste de fumaça de toda integração nova.
{
"conta": { "id": 1, "name": "Minha Empresa", "slug": "principal" },
"chave_id": 3
}
GET /api/v1/pedidos
Lista os seus pedidos, do mais novo para o mais velho.
Parâmetros (query string)
| Parâmetro | Descrição |
|---|---|
status | Filtra por status: pending, paid, refused, refunded, chargeback, expired, canceled. |
limite | Quantos por página (1 a 100; padrão 25). |
antes_de | Paginação: o id do último pedido da página anterior. Devolve os anteriores a ele. |
curl "https://mitzpay.com/api/v1/pedidos?status=paid&limite=2" \
-H "Authorization: Bearer mitz_SUA_CHAVE_AQUI"
{
"data": [
{
"id": "0b7a4b62-91a4-4c3e-9d55-1f2ab34cd901",
"codigo": "MZ48210375",
"status": "paid",
"tipo": "main",
"metodo_pagamento": "pix",
"valor_cents": 19700,
"desconto_cents": 0,
"parcelas": 1,
"gateway": "asaas",
"produto": { "id": 12, "nome": "Curso de Tráfego" },
"comprador": { "nome": "Maria da Silva", "email": "maria@exemplo.com" },
"criado_em": "2026-08-16T14:02:11.000Z",
"pago_em": "2026-08-16T14:03:40.000Z"
}
],
"tem_mais": true
}
valor_cents: 19700 = R$ 197,00)
e datas em ISO-8601 (UTC). Para a próxima página, repita a chamada com
antes_de=<id do último da lista> até tem_mais vir false.
GET /api/v1/pedidos/:id
Um pedido específico, com os itens (produto principal, order bumps, upsell).
{
"data": {
"id": "0b7a4b62-91a4-4c3e-9d55-1f2ab34cd901",
"codigo": "MZ48210375",
"status": "paid",
"...": "...",
"itens": [
{ "kind": "main", "title": "Curso de Tráfego", "amount_cents": 19700 },
{ "kind": "bump", "title": "Planilha de campanhas", "amount_cents": 4700 }
]
}
}
Webhooks: como funcionam
Quando um pedido nasce ou muda de status, a Mitzpay envia um POST com corpo JSON para as URLs que você cadastrar em Painel → Integrações. É assim que sua área de membros libera acesso, seu CRM registra a venda e seu sistema de mensagens dispara o WhatsApp, tudo em tempo real, sem ficar consultando a API.
- Cadastre a URL do seu sistema (precisa ser um endereço público, HTTPS de preferência).
- Guarde o segredo exibido na criação: é ele que valida cada entrega.
- Escolha quais eventos quer receber (nenhum marcado = todos).
- Use o botão testar do painel para receber um evento de exemplo na hora.
Eventos
| Evento | Quando dispara |
|---|---|
checkout.started | Alguém preencheu o e-mail no checkout: nasceu uma intenção de compra. |
checkout.abandoned | A pessoa preencheu e não pagou em 15 minutos. O corpo traz a recovery_url, o link que reabre o checkout já preenchido. |
order.created | O pedido nasceu e está aguardando pagamento (Pix gerado, boleto emitido, cartão em processamento). |
order.paid | Pagamento confirmado. É o evento de liberar a entrega. |
order.refused | O pagamento foi recusado (cartão negado). |
order.refunded | O pedido foi devolvido ao comprador. |
order.chargeback | O comprador contestou a cobrança no banco/cartão. |
order.expired | O prazo do Pix/boleto venceu sem pagamento. |
Payload
Todo evento tem o mesmo envelope; o que muda é o event e o conteúdo de data. Os eventos de pedido (order.*) trazem o pedido completo:
{
"event": "order.paid",
"created_at": "2026-08-16T14:03:40.512Z",
"data": {
"order_id": "0b7a4b62-91a4-4c3e-9d55-1f2ab34cd901",
"parent_order_id": null,
"kind": "main",
"status": "paid",
"payment_method": "pix",
"amount_cents": 24400,
"installments": 1,
"gateway": "asaas",
"paid_at": "2026-08-16T14:03:40.000Z",
"product": { "id": 12, "name": "Curso de Tráfego", "slug": "curso-de-trafego" },
"buyer": {
"name": "Maria da Silva",
"email": "maria@exemplo.com",
"document": "52998224725",
"phone": "11999998888"
},
"items": [
{ "kind": "main", "title": "Curso de Tráfego", "amount_cents": 19700 },
{ "kind": "bump", "title": "Planilha de campanhas", "amount_cents": 4700 }
]
}
}
Os eventos de checkout (checkout.started e checkout.abandoned) trazem a
intenção de compra e o link de recuperação. É com a recovery_url que seu CRM,
automação ou WhatsApp chama a pessoa de volta: o link reabre o checkout com os dados já preenchidos.
{
"event": "checkout.abandoned",
"created_at": "2026-08-16T15:20:03.412Z",
"data": {
"recovery_url": "https://mitzpay.com/r/a1b2c3d4e5f6...",
"buyer": { "name": "Maria da Silva", "email": "maria@exemplo.com", "phone": "11999998888" },
"product": { "id": 12, "name": "Curso de Tráfego", "slug": "curso-de-trafego" },
"coupon_code": null,
"tracking": { "utm_source": "instagram", "utm_campaign": "lancamento" },
"session_created_at": "2026-08-16T15:05:01.000Z"
}
}
E estes cabeçalhos acompanham cada entrega:
| Cabeçalho | Conteúdo |
|---|---|
X-Mitz-Event | O evento (ex.: order.paid). |
X-Mitz-Delivery | Id único desta entrega. Use para descartar duplicatas. |
X-Mitz-Timestamp | Segundos unix do envio. |
X-Mitz-Signature | sha256=<HMAC>: a assinatura (abaixo). |
Validar a assinatura
A assinatura prova duas coisas: que o aviso veio da Mitzpay (só nós temos o segredo do seu destino) e que não é uma captura reapresentada (o timestamp entra no cálculo). Valide toda entrega antes de confiar nela:
- Monte a string
timestamp + "." + corpo cru(o corpo exatamente como chegou, sem re-serializar). - Calcule o HMAC-SHA256 dessa string com o segredo do destino, em hexadecimal.
- Compare
"sha256=" + resultadocom o cabeçalhoX-Mitz-Signature, em comparação de tempo constante. - Rejeite se o
X-Mitz-Timestampestiver a mais de 5 minutos do seu relógio.
Node.js (Express)
const crypto = require("crypto");
// use express.raw() ou guarde o corpo cru: JSON.stringify(req.body) NÃO serve
app.post("/webhook-mitz", express.raw({ type: "application/json" }), (req, res) => {
const ts = req.get("x-mitz-timestamp");
const recebida = req.get("x-mitz-signature") || "";
const esperada = "sha256=" + crypto.createHmac("sha256", process.env.MITZ_SEGREDO)
.update(`${ts}.${req.body}`).digest("hex");
const valida = recebida.length === esperada.length &&
crypto.timingSafeEqual(Buffer.from(recebida), Buffer.from(esperada));
if (!valida || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
return res.status(401).end();
}
const evento = JSON.parse(req.body);
// confirme rápido; processe depois
res.status(200).end();
});
PHP
$segredo = getenv("MITZ_SEGREDO");
$ts = $_SERVER["HTTP_X_MITZ_TIMESTAMP"] ?? "";
$recebida = $_SERVER["HTTP_X_MITZ_SIGNATURE"] ?? "";
$corpo = file_get_contents("php://input");
$esperada = "sha256=" . hash_hmac("sha256", $ts . "." . $corpo, $segredo);
if (!hash_equals($esperada, $recebida) || abs(time() - (int)$ts) > 300) {
http_response_code(401);
exit;
}
$evento = json_decode($corpo, true);
http_response_code(200);
Retentativas
Se o seu sistema não responder 2xx (erro, queda, demora além de 10 segundos), a Mitzpay tenta de novo com espera crescente, até 6 tentativas no total:
| Tentativa | 1ª | 2ª | 3ª | 4ª | 5ª | 6ª |
|---|---|---|---|---|---|---|
| Espera após a falha | imediata | 1 min | 5 min | 30 min | 2 h | 6 h |
Depois disso a entrega fica marcada como falhou, e você pode reenviá-la manualmente a qualquer momento na lista de entregas do painel, que mostra o histórico com o código HTTP de cada tentativa.
Boas práticas
- Confirme rápido, processe depois. Grave o evento numa fila sua e responda 200 na hora; não faça o processamento pesado dentro da requisição.
- Trate duplicatas. Em rede, "pelo menos uma vez" é a única garantia possível: use o
X-Mitz-Delivery(oudata.order_id+event) para ignorar o que já processou. - Não confie na ordem. Um
order.paidpode chegar antes doorder.createdse houver retentativa no meio. Trate cada evento pelo estado que ele carrega. - Valide a assinatura sempre, inclusive em ambiente de teste. É a diferença entre "aviso da Mitzpay" e "POST de qualquer um".
- Endereço público. URLs internas (localhost, IP de rede privada) são recusadas no cadastro e no envio.
Widget de página de vendas
Para vender upsell e downsell na sua própria página (fora do checkout),
a Mitzpay oferece um widget de 1 clique: o construtor de funil do painel gera um
<script> pronto para colar na página, e o botão cobra o cartão salvo
da compra original sem o comprador redigitar nada.
O snippet é gerado por produto em Painel → Produtos → Funil; cada token de widget vale para uma etapa e morre no primeiro aceite.
Changelog
| Data | Mudança |
|---|---|
| 2026-08-16 | Eventos de recuperação de venda: checkout.started e checkout.abandoned, com a recovery_url no corpo para o seu CRM ou automação chamar a pessoa de volta. |
| 2026-08-16 | Lançamento desta documentação. API v1 (/eu, /pedidos) com chave por conta; evento novo order.created; assinatura dos webhooks passa a cobrir o timestamp (X-Mitz-Timestamp, anti-replay); retentativas em fila separada por destino. |