Developers Acessar

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
Comece em 2 minutos: gere uma chave em Painel → Integrações → Chaves de API e chame 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ódigoSignificado
200Deu certo. O corpo traz o resultado em JSON.
400Parâmetro inválido. O corpo diz qual, em { "erro": "..." }.
401Chave ausente, inválida ou revogada.
404O recurso não existe, ou não é seu (a API não diferencia, de propósito).
429Limite de requisições atingido. Aguarde e tente de novo.
500Erro 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âmetroDescrição
statusFiltra por status: pending, paid, refused, refunded, chargeback, expired, canceled.
limiteQuantos por página (1 a 100; padrão 25).
antes_dePaginaçã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
}
Dinheiro é sempre em centavos (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.

  1. Cadastre a URL do seu sistema (precisa ser um endereço público, HTTPS de preferência).
  2. Guarde o segredo exibido na criação: é ele que valida cada entrega.
  3. Escolha quais eventos quer receber (nenhum marcado = todos).
  4. Use o botão testar do painel para receber um evento de exemplo na hora.
Responda HTTP 2xx em até 10 segundos. Qualquer outra resposta (ou demora) conta como falha e entra na fila de retentativas. Se o seu processamento é demorado, confirme primeiro e processe depois.

Eventos

EventoQuando dispara
checkout.startedAlguém preencheu o e-mail no checkout: nasceu uma intenção de compra.
checkout.abandonedA pessoa preencheu e não pagou em 15 minutos. O corpo traz a recovery_url, o link que reabre o checkout já preenchido.
order.createdO pedido nasceu e está aguardando pagamento (Pix gerado, boleto emitido, cartão em processamento).
order.paidPagamento confirmado. É o evento de liberar a entrega.
order.refusedO pagamento foi recusado (cartão negado).
order.refundedO pedido foi devolvido ao comprador.
order.chargebackO comprador contestou a cobrança no banco/cartão.
order.expiredO 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çalhoConteúdo
X-Mitz-EventO evento (ex.: order.paid).
X-Mitz-DeliveryId único desta entrega. Use para descartar duplicatas.
X-Mitz-TimestampSegundos unix do envio.
X-Mitz-Signaturesha256=<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:

  1. Monte a string timestamp + "." + corpo cru (o corpo exatamente como chegou, sem re-serializar).
  2. Calcule o HMAC-SHA256 dessa string com o segredo do destino, em hexadecimal.
  3. Compare "sha256=" + resultado com o cabeçalho X-Mitz-Signature, em comparação de tempo constante.
  4. Rejeite se o X-Mitz-Timestamp estiver 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
Espera após a falhaimediata1 min5 min30 min2 h6 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 (ou data.order_id + event) para ignorar o que já processou.
  • Não confie na ordem. Um order.paid pode chegar antes do order.created se 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

DataMudança
2026-08-16Eventos 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-16Lanç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.