# HyzePay — Documentação completa para implementação (IA / dev) > Arquivo auto-contido. Qualquer dev ou LLM consegue integrar PIX + webhooks só com este texto. > Versão da API: v1 · Formato: JSON · Moeda: BRL (centavos) Site: https://hyzepay.pro Docs humanas: https://hyzepay.pro/docs Índice curto: https://hyzepay.pro/llms.txt --- ## 1. Visão geral HyzePay é um gateway de pagamento brasileiro. A API externa gera cobranças PIX, devolve QR/copia-e-cola, permite consultar status e notifica o seu backend via webhooks assinado com HMAC. **Regras de ouro** 1. API Key só no servidor (nunca no frontend/browser). 2. Valores em **centavos**: `amount_cents` (R$ 15,00 → `1500`). 3. Sempre envie `external_id` (idempotência + amarra o pedido no seu sistema). 4. Liberar produto **somente** com `status === "paid"`. 5. Preferir webhook `payment.paid` com validação HMAC; polling como fallback. ### Base URL e prefixo ``` Base URL: https://hyzepay.pro (ou o domínio da sua instância) Prefixo: /api/v1 Auth: Authorization: Bearer hzp_live_… OU X-API-Key: hzp_live_… ``` Header de resposta: `X-HyzePay-API-Version: v1` --- ## 2. Autenticação e API Keys ### Usar a chave ```http Authorization: Bearer hzp_live_XXXXXXXXXXXXXXXXXXXXXXXX Content-Type: application/json ``` ### Escopos | Scope | Permite | |-------|---------| | `payments:write` | Criar e cancelar pagamentos | | `payments:read` | Consultar e listar | | `*` | Tudo | Chaves criadas no dashboard vêm com `payments:read` + `payments:write`. ### Criar chave (dashboard, sessão logada + 2FA) ```http POST /api/api-keys Content-Type: application/json { "name": "Meu backend", "totpCode": "123456" } ``` A `secret` só aparece **uma vez**. Revogar: `DELETE /api/api-keys/{id}`. Listar: `GET /api/api-keys`. --- ## 3. Endpoints ### 3.1 Health (sem auth) ```http GET /api/v1/health ``` ```json { "ok": true, "service": "hyzepay-api", "version": "v1", "gateway": { "provider": "woovi", "configured": true }, "time": "2026-07-13T12:00:00.000Z" } ``` ### 3.2 Criar pagamento ```http POST /api/v1/payments Authorization: Bearer hzp_live_… Content-Type: application/json ``` **Body** | Campo | Tipo | Obrigatório | Descrição | |-------|------|-------------|-----------| | `amount_cents` | number | sim* | Valor em centavos | | `amount` | number | sim* | Alternativa em reais | | `description` | string | não | Texto do PIX (~140 chars) | | `external_id` | string | não | ID no seu sistema (idempotente) | | `expires_in` | number | não | 60–86400 segundos (default 24h) | | `customer.name` | string | não | Nome | | `customer.email` | string | não | E-mail | | `customer.document` | string | não | CPF/CNPJ | | `customer.phone` | string | não | Telefone | | `metadata` | object | não | JSON livre | \* `amount_cents` **ou** `amount`. Aceita camelCase: `amountCents`, `externalId`, `expiresIn`. **Exemplo** ```json { "amount_cents": 9900, "description": "Assinatura Pro", "external_id": "order_42", "expires_in": 3600, "customer": { "name": "João Souza", "email": "joao@empresa.com", "document": "12345678909", "phone": "11999998888" }, "metadata": { "user_id": "42", "plan": "pro" } } ``` **Resposta 201 (criado) ou 200 (idempotente)** ```json { "payment": { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "pending", "amount_cents": 9900, "amount_label": "R$ 99,00", "currency": "BRL", "description": "Assinatura Pro", "external_id": "order_42", "customer": { "name": "João Souza", "email": "joao@empresa.com", "document": "12345678909", "phone": "11999998888" }, "pix": { "br_code": "00020126…6304ABCD", "qr_code_image": "https://… ou data:image/png;base64,…", "payment_link_url": "https://…", "expires_at": "2026-07-13T13:00:00.000Z" }, "checkout_url": "https://hyzepay.pro/pay/api_xxxxx", "metadata": { "user_id": "42", "plan": "pro" }, "correlation_id": "…", "created_at": "2026-07-13T12:00:00.000Z", "updated_at": "2026-07-13T12:00:00.000Z", "paid_at": null }, "created": true } ``` Use **`payment.pix.br_code`** no copia-e-cola PIX. ### 3.3 Consultar pagamento ```http GET /api/v1/payments/{id} Authorization: Bearer hzp_live_… ``` `{id}` = UUID HyzePay **ou** seu `external_id`. Se ainda `pending`, a API pode sincronizar com o gateway e atualizar para `paid`/`expired`. **Polling sugerido:** a cada 3–5s enquanto `pending`; parar em `paid|expired|failed|refunded`. ### 3.4 Listar pagamentos ```http GET /api/v1/payments?status=pending&limit=20&offset=0 Authorization: Bearer hzp_live_… ``` Query: `status`, `external_id`, `limit` (max 100, default 20), `offset`. ```json { "payments": [ /* Payment[] */ ], "pagination": { "limit": 20, "offset": 0, "total": 42 } } ``` ### 3.5 Cancelar pagamento ```http DELETE /api/v1/payments/{id} Authorization: Bearer hzp_live_… ``` Só para `pending` → vira `expired`. Se já `paid` → erro `already_paid`. --- ## 4. Objeto Payment | Campo | Tipo | Descrição | |-------|------|-----------| | `id` | uuid | ID HyzePay | | `status` | string | pending \| paid \| expired \| failed \| refunded | | `amount_cents` | number | Centavos | | `amount_label` | string | Ex.: "R$ 99,00" | | `currency` | "BRL" | Sempre BRL | | `description` | string\|null | Descrição | | `external_id` | string\|null | Seu ID | | `customer` | object | Pagador | | `pix.br_code` | string\|null | PIX copia-e-cola | | `pix.qr_code_image` | string\|null | URL ou data-URI do QR | | `pix.payment_link_url` | string\|null | Link do provedor | | `pix.expires_at` | string\|null | ISO 8601 | | `checkout_url` | string\|null | Página HyzePay `/pay/…` | | `metadata` | object\|null | Seu JSON | | `correlation_id` | string\|null | ID no gateway | | `created_at` | string | ISO 8601 | | `updated_at` | string\|null | ISO 8601 | | `paid_at` | string\|null | Quando pagou | --- ## 5. Erros ```json { "error": { "code": "invalid_amount", "message": "Informe amount_cents (>= 1) ou amount em reais.", "details": null } } ``` | HTTP | code | Quando | |------|------|--------| | 400 | `invalid_json` | Body inválido | | 400 | `invalid_amount` | Valor inválido | | 400 | `amount_too_large` | Acima do limite | | 400 | `invalid_expires_in` | Fora de 60–86400 | | 400 | `already_paid` | Cancelar pago | | 401 | `unauthorized` / `invalid_api_key` / `api_key_revoked` / `api_key_expired` | Auth | | 403 | `forbidden_scope` | Escopo insuficiente | | 404 | `not_found` | Pagamento inexistente | | 502 | `pix_generation_failed` | Gateway falhou | | 503 | `gateway_unavailable` | Gateway não configurado | --- ## 6. Idempotência Envie sempre `external_id` estável (ex.: `order_123`). - 1º POST → cria (`created: true`) - 2º POST com mesmo `external_id` → devolve o mesmo payment (`created: false`) - Não gera segundo PIX --- ## 7. Webhooks Cadastro: Dashboard → Integração → Webhook → URL HTTPS + secret (`whsec_…`) + eventos. ### Headers | Header | Exemplo | |--------|---------| | `Content-Type` | `application/json` | | `User-Agent` | `HyzePay-Webhooks/2.0` | | `X-HyzePay-Event` | `payment.paid` | | `X-HyzePay-Event-Id` | `evt_…` | | `X-HyzePay-Delivery` | `dlv_…` | | `X-HyzePay-Webhook-Id` | `wh_…` | | `X-HyzePay-Signature` | `t=1710000000,v1=hex…` | | `X-HyzePay-Api-Version` | `v2` | ### Assinatura HMAC (obrigatória) 1. `t` = timestamp Unix (segundos) do header 2. `signedPayload = `${t}.${rawBody}`` — rawBody = bytes UTF-8 exatos do POST 3. `v1 = HMAC_SHA256(secret, signedPayload)` em hex 4. Header: `X-HyzePay-Signature: t=,v1=` 5. Rejeitar se `|now - t| > 300` 6. Comparar com timing-safe equal ### Node.js ```ts import { createHmac, timingSafeEqual } from "crypto"; export function verifyHyzePaySignature(opts: { secret: string; rawBody: string; signatureHeader: string; toleranceSec?: number; }): boolean { const tolerance = opts.toleranceSec ?? 300; const parts = opts.signatureHeader.split(",").map((p) => p.trim()); let t: number | null = null; const signatures: string[] = []; for (const part of parts) { const [k, v] = part.split("="); if (k === "t" && v) t = Number(v); if (k === "v1" && v) signatures.push(v); } if (t == null || !Number.isFinite(t) || signatures.length === 0) return false; if (Math.abs(Math.floor(Date.now() / 1000) - t) > tolerance) return false; const expected = createHmac("sha256", opts.secret) .update(`${t}.${opts.rawBody}`, "utf8") .digest("hex"); const expectedBuf = Buffer.from(expected, "utf8"); return signatures.some((sig) => { try { const got = Buffer.from(sig, "utf8"); return got.length === expectedBuf.length && timingSafeEqual(got, expectedBuf); } catch { return false; } }); } ``` ### Next.js App Router ```ts export async function POST(req: Request) { const rawBody = await req.text(); const sig = req.headers.get("x-hyzepay-signature") || ""; if (!verifyHyzePaySignature({ secret: process.env.HYZEPAY_WEBHOOK_SECRET!, rawBody, signatureHeader: sig, })) { return Response.json({ error: "invalid_signature" }, { status: 401 }); } const event = JSON.parse(rawBody); // v2: event.type + event.data.object // v1: event.event + event.data return Response.json({ received: true }); } ``` ### Eventos | Evento | Uso típico | |--------|------------| | `payment.created` | Log | | **`payment.paid`** | **Liberar produto** | | `payment.expired` | Cancelar pedido / estoque | | `payment.failed` | Notificar usuário | | `payment.refunded` | Revogar acesso | | `dispute.created` / `dispute.updated` | Pausar entrega | | `withdrawal.requested` / `withdrawal.paid` | Contabilidade | | `test` | Botão “Enviar teste” no painel | ### Payload v2 (recomendado) ```json { "id": "evt_abc123", "type": "payment.paid", "api_version": "v2", "created": 1710000000, "created_at": "2026-03-09T12:00:00.000Z", "livemode": true, "data": { "object": { "id": "uuid-do-pedido", "status": "paid", "amount_cents": 1990, "amount_label": "R$ 19,90", "currency": "BRL", "payment_method": "pix", "external_id": "order_123", "description": "Plano Pro", "customer": { "name": "Maria", "email": "maria@email.com", "document": "12345678909", "phone": null }, "metadata": { "sku": "PRO-1" }, "fee_cents": 59, "paid_at": "…", "created_at": "…", "updated_at": "…" } }, "source": "hyzepay" } ``` ### Payload v1 (legado) ```json { "event": "payment.paid", "event_id": "evt_abc123", "created_at": "…", "livemode": true, "data": { "id": "…", "status": "paid", "amount_cents": 1990, "external_id": "order_123" }, "source": "hyzepay", "api_version": "v1" } ``` ### Regras para liberar produto em payment.paid 1. Assinatura HMAC válida 2. type/event === `payment.paid` 3. status === `paid` 4. Conferir `amount_cents` com o pedido interno 5. Usar `external_id` ou `id` para achar o pedido 6. Se já processou `event.id` / `event_id`, ignore (idempotência) 7. Responder HTTP 2xx rápido --- ## 8. Exemplos de cliente ### TypeScript ```ts const BASE = process.env.HYZEPAY_BASE_URL!; const KEY = process.env.HYZEPAY_API_KEY!; async function hyzeFetch(path: string, init: RequestInit = {}) { const res = await fetch(`${BASE}${path}`, { ...init, headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json", ...(init.headers || {}), }, }); const data = await res.json(); if (!res.ok) throw new Error(data?.error?.message || `HTTP ${res.status}`); return data; } const { payment, created } = await hyzeFetch("/api/v1/payments", { method: "POST", body: JSON.stringify({ amount_cents: 2500, description: "Pedido #99", external_id: "pedido-99", customer: { name: "Ana", email: "ana@x.com" }, }), }); console.log("PIX:", payment.pix.br_code, "created:", created); async function waitPaid(id: string, timeoutMs = 15 * 60 * 1000) { const start = Date.now(); while (Date.now() - start < timeoutMs) { const { payment } = await hyzeFetch(`/api/v1/payments/${id}`); if (payment.status === "paid") return payment; if (["expired", "failed", "refunded"].includes(payment.status)) { throw new Error(`Pagamento ${payment.status}`); } await new Promise((r) => setTimeout(r, 4000)); } throw new Error("Timeout aguardando pagamento"); } ``` ### Python ```python import os, time, requests BASE = os.environ["HYZEPAY_BASE_URL"] KEY = os.environ["HYZEPAY_API_KEY"] H = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"} r = requests.post(f"{BASE}/api/v1/payments", headers=H, json={ "amount_cents": 1500, "description": "Pedido Python", "external_id": "py-100", }) r.raise_for_status() payment = r.json()["payment"] print("PIX:", payment["pix"]["br_code"]) ``` ### cURL ```bash curl -X POST "$HYZEPAY_BASE_URL/api/v1/payments" \ -H "Authorization: Bearer $HYZEPAY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount_cents": 1500, "description": "Pedido #1001", "external_id": "pedido-1001", "customer": { "name": "Maria Silva", "email": "maria@email.com", "document": "12345678909" } }' ``` --- ## 9. Fluxo recomendado ``` Seu backend --POST /payments--> HyzePay --PIX--> Gateway ^ | | br_code + qr | +-------------------------------+ | | mostra QR ao cliente | | webhook payment.paid (ou poll GET /payments/:id) v liberar produto se status=paid ``` 1. `POST /api/v1/payments` com `external_id` 2. Exibir `pix.br_code` / QR 3. Confirmar via webhook **ou** poll até `paid`/`expired` 4. Liberar só com `paid` --- ## 10. Checklist de integração - [ ] API key criada e salva no backend (`.env`) - [ ] `POST /api/v1/payments` retorna `pix.br_code` - [ ] UI mostra QR / copia-e-cola - [ ] `external_id` em todas as criações - [ ] Webhook HTTPS cadastrado com `payment.paid` - [ ] Endpoint valida `X-HyzePay-Signature` - [ ] Liberação só com `status === "paid"` - [ ] Idempotência de eventos (`event.id`) - [ ] Polling como fallback (opcional) - [ ] Secret e API key nunca no frontend --- ## 11. Prompt compacto para colar na IA ``` Integre HyzePay API v1 no meu backend. Base: {{HYZEPAY_BASE_URL}} Auth: Authorization: Bearer {{HYZEPAY_API_KEY}} Docs full: https://hyzepay.pro/llms-full.txt POST /api/v1/payments { amount_cents, description?, external_id?, customer?, metadata?, expires_in? } → payment.pix.br_code, payment.id, status pending|paid|expired|failed|refunded, created boolean GET /api/v1/payments/:id (UUID ou external_id) GET /api/v1/payments?status=&limit=&offset= DELETE /api/v1/payments/:id GET /api/v1/health Webhook: X-HyzePay-Signature = t=,v1=HMAC_SHA256(secret, `${t}.${rawBody}`) hex Evento payment.paid (v2: data.object). Liberar só se status=paid. Idempotência por event.id. Regras: server-only; sempre external_id; amount_cents; created:false = ok. Implemente client tipado + createAndWaitForPayment + webhook HMAC. ``` --- ## 12. Links | Recurso | URL | |---------|-----| | Docs | https://hyzepay.pro/docs | | PIX ref | https://hyzepay.pro/docs/referencia/pix | | Webhooks | https://hyzepay.pro/docs/webhooks | | Segurança | https://hyzepay.pro/docs/webhooks/seguranca | | Chaves | https://hyzepay.pro/docs/guias/chaves-de-api | | Índice LLM | https://hyzepay.pro/llms.txt | | Este arquivo | https://hyzepay.pro/llms-full.txt | | Dashboard | https://hyzepay.pro/dashboard | --- *HyzePay API v1 — PIX · Webhooks HMAC · Feito para devs e IAs*