docs

Quickstart

Sua primeira cobrança em 5 minutos com cURL ou Node 18+ fetch — sem SDK, sem dependência.

Este guia leva você de zero à primeira cobrança bem-sucedida em modo de teste, sem nenhuma adquirente real envolvida. No final, você terá:

  1. Uma chave de API de teste (zsk_test_*).
  2. Um PaymentIntent criado via API.
  3. Um webhook recebido no seu servidor local com a confirmação do pagamento.

Tudo em HTTP purocurl ou fetch nativo do Node 18+. Sem SDK, sem dependência.

Modo de teste vs. modo live

Tudo neste guia usa chaves *_test_*. Elas tocam o MockAcquirerAdapter interno — você nunca vai mover dinheiro real. Para ir para produção é só trocar pela chave zsk_live_*.

1. Crie sua conta e pegue uma chave

Crie sua conta em app.zhex.io e vá em Developers → API keys.

Você verá quatro tipos de chaves:

PrefixoUsoOnde
zk_test_…Publishable, modo testeFront-end (ex.: zhex.js)
zsk_test_…Secret, modo testeServidor (somente backend!)
zk_live_…Publishable, produçãoFront-end
zsk_live_…Secret, produçãoServidor

Copie a chave zsk_test_… e guarde como variável de ambiente:

export ZHEX_SECRET_KEY=zsk_test_abcd1234efgh5678

Nunca commite chaves secretas

zsk_* deve viver apenas em variáveis de ambiente do servidor. A Zhex monitora chaves vazadas no GitHub via Secret Scanning — se sua chave for detectada em commit público ela é revogada automaticamente.

2. Crie um Customer

Antes de cobrar, crie o cliente — customer é parâmetro obrigatório no PaymentIntent.

curl https://prometheus.zhex.io/v1/customers \
  -H "Authorization: Bearer $ZHEX_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "cliente@exemplo.com.br",
    "name": "Cliente Teste",
    "document": "12345678909"
  }'

3. Faça sua primeira cobrança

Crie um PaymentIntent de R$ 49,90 em PIX, apontando para o customer recém-criado.

curl https://prometheus.zhex.io/v1/payment_intents \
  -H "Authorization: Bearer $ZHEX_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Zhex-Version: 2026-04-25" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4990,
    "currency": "brl",
    "customer": "cus_…",
    "payment_method_types": ["pix"],
    "description": "Primeira cobrança Zhex"
  }'

A resposta vai ter o seguinte formato:

{
  "id": "pi_3MtwBwLkdIwHu7ix28a3tqPa",
  "object": "payment_intent",
  "livemode": false,
  "amount": 4990,
  "currency": "brl",
  "status": "requires_payment_method",
  "customer": "cus_…",
  "description": "Primeira cobrança Zhex",
  "payment_method_types": ["pix"],
  "last_payment_error": null,
  "charges": { "latest": null },
  "created": 1714057200
}

Para liquidar em test mode, dispare o helper:

curl -X POST "https://prometheus.zhex.io/v1/test_helpers/payment_intents/pi_…/succeed" \
  -H "Authorization: Bearer $ZHEX_SECRET_KEY"
# webhook payment_intent.succeeded é entregue em segundos

4. Receba o webhook de confirmação

Em vez de ficar fazendo polling no GET /v1/payment_intents/:id, você recebe um evento HTTP assim que o pagamento confirma.

3.1. Crie o endpoint local

import express from 'express';
import { createHmac, timingSafeEqual } from 'node:crypto';

const app = express();

app.post(
  '/webhooks/zhex',
  // CRÍTICO: raw body. express.json() quebra a assinatura.
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const sig = req.header('zhex-signature') ?? '';
    const parts = Object.fromEntries(
      sig.split(',').map((kv) => kv.split('=')),
    ) as { t?: string; v1?: string };

    const secret = process.env.ZHEX_WEBHOOK_SECRET!;
    const body = req.body.toString('utf8');
    const expected = createHmac('sha256', secret)
      .update(`${parts.t}.${body}`)
      .digest('hex');

    const a = Buffer.from(parts.v1 ?? '', 'hex');
    const b = Buffer.from(expected, 'hex');
    if (a.length !== b.length || !timingSafeEqual(a, b)) {
      return res.status(400).send('Invalid signature');
    }

    const event = JSON.parse(body);
    if (event.type === 'payment_intent.succeeded') {
      const intent = event.data.object;
      console.log('PIX confirmado:', intent.id, intent.amount);
    }

    res.json({ received: true });
  },
);

app.listen(3000, () => console.log('Listening on http://localhost:3000'));

3.2. Exponha o localhost com ngrok (ou cloudflared)

Pra dev local, use um tunnel HTTPS pra expor seu localhost e cadastre um webhook endpoint apontando pra ele:

# Em um terminal: sobe seu app
node server.js

# Em outro: tunnel pra porta 3000
ngrok http 3000
# → Forwarding  https://abc123.ngrok-free.app -> http://localhost:3000

3.3. Cadastre o endpoint na Zhex

curl https://prometheus.zhex.io/v1/webhook_endpoints \
  -H "Authorization: Bearer $ZHEX_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://abc123.ngrok-free.app/webhooks/zhex",
    "events": ["payment_intent.succeeded", "payment_intent.payment_failed"]
  }'

Response:

{
  "id": "we_1MtwBwLkdI",
  "url": "https://abc123.ngrok-free.app/webhooks/zhex",
  "secret": "whsec_test_xyz123...",
  "events": ["payment_intent.succeeded", "payment_intent.payment_failed"],
  "livemode": false
}

Exporte o whsec_*:

export ZHEX_WEBHOOK_SECRET=whsec_test_xyz123...

E reinicie seu app pra ele pegar o env atualizado.

5. Pagamento confirmado

Em test mode, o mock acquirer "paga" o PIX automaticamente após ~3s da criação do PaymentIntent. Você verá no terminal:

PIX confirmado: pi_3MtwBwLkdIwHu7ix28a3tqPa 4990

E pode confirmar via API:

curl https://prometheus.zhex.io/v1/payment_intents/pi_3MtwBwLkdIwHu7ix28a3tqPa \
  -H "Authorization: Bearer $ZHEX_SECRET_KEY"
# → "status": "succeeded"
  1. Pegou a chave zsk_test_… e exportou no env.
  2. Criou um PaymentIntent via fetch com Idempotency-Key.
  3. Recebeu o webhook com tunnel + assinatura HMAC validada.
  4. Confirmou o pagamento quando payment_intent.succeeded chegou.

Próximos passos

Esta página foi útil?

Atualizado em

Nesta página