Voren API v1

Integre pagamentos, produtos e webhooks em minutos.

REST previsível, autenticação HTTP Basic, chaves com escopos, idempotência e webhooks assinados HMAC-SHA256.

Base URL: https://appvoren.com.br/api/public/v1

Autenticação

Toda requisição usa HTTP Basic com seu client_id como usuário e client_secret como senha. Crie chaves em /voren-api.

curl https://appvoren.com.br/api/public/v1/ping \
  -u "vrn_id_xxx:vrn_live_yyy"

Quickstart em 3 passos

  1. Ative seu recebedor Pagar.me e crie uma chave em /voren-api.
  2. Crie um produto via API (ou use um existente).
  3. Gere uma cobrança e receba o resultado por webhook.
# 1) Criar produto
curl -X POST https://appvoren.com.br/api/public/v1/products \
  -u "$KEY_ID:$KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"name":"Curso Voren","price_cents":9700,"status":"active","delivery_methods":["link"],"delivery_url":"https://area.example.com"}'

# 2) Gerar Pix
curl -X POST https://appvoren.com.br/api/public/v1/charges \
  -u "$KEY_ID:$KEY_SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1001" \
  -d '{
    "product_id":"<uuid>",
    "payment_method":"pix",
    "customer":{"name":"Ana Silva","email":"ana@example.com","document":"12345678909","phone":"11999998888"}
  }'

Escopos e ambientes

Cada chave tem escopos e ambiente (live ou test). Chame apenas o mínimo necessário.

  • products.read, products.write
  • sales.read, sales.write (inclui cobranças e estornos)
  • subscriptions.read, customers.read
  • webhooks.manage

Idempotência

Envie um header Idempotency-Key em POST. Requisições repetidas com a mesma chave retornam o mesmo recurso e o header Idempotency-Replayed: true.

Rate limits

300 requisições por minuto por chave. Ao exceder, respondemos 429 com header Retry-After em segundos.

Formato de erro

Todos os erros usam JSON estável:

{
  "error": "invalid_request",
  "message": "Descrição legível do problema.",
  "request_id": "req_ab12cd34...",
  "details": [{ "path": "customer.email", "message": "Invalid email" }]
}

Códigos comuns: unauthorized, invalid_credentials, insufficient_scope, invalid_request, not_found, invalid_state, rate_limited, provider_error, internal_error.

Products

GET/v1/productsscope: products.read
POST/v1/productsscope: products.write
GET/v1/products/{id}scope: products.read
PATCH/v1/products/{id}scope: products.write
curl -X POST https://appvoren.com.br/api/public/v1/products \
  -u "$KEY_ID:$KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "name":"Mentoria Voren",
    "description":"3 meses de acompanhamento",
    "price_cents":149700,
    "status":"active",
    "delivery_methods":["email"],
    "support_email":"suporte@example.com"
  }'

Charges (cobranças)

POST/v1/chargesscope: sales.write
GET/v1/chargesscope: sales.read
GET/v1/charges/{id}scope: sales.read

Preço e divisão (split) são sempre calculados no servidor — o campo amount nunca vem do cliente. Métodos: pix, boleto, credit_card.

curl -X POST https://appvoren.com.br/api/public/v1/charges \
  -u "$KEY_ID:$KEY_SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cli-2025-0001" \
  -d '{
    "product_id":"<uuid>",
    "offer_id":"<uuid>",
    "payment_method":"credit_card",
    "card_token":"card_token_xxx",
    "installments":3,
    "customer":{"name":"Ana","email":"ana@x.com","document":"12345678909","phone":"11999998888"},
    "coupon_code":"BEMVINDO10",
    "ref_code":"abc123",
    "metadata":{"origin":"landing-a"}
  }'

Refunds (estornos)

POST/v1/refundsscope: sales.write

Suporta estorno total ou parcial. Envie sale_id (ou charge_id) e opcionalmente amount_cents para parcial.

# Estorno total
curl -X POST https://appvoren.com.br/api/public/v1/refunds \
  -u "$KEY_ID:$KEY_SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: refund-2025-0001" \
  -d '{"sale_id":"<uuid>","reason":"solicitação do cliente"}'

# Estorno parcial (R$ 30,00)
curl -X POST https://appvoren.com.br/api/public/v1/refunds \
  -u "$KEY_ID:$KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"sale_id":"<uuid>","amount_cents":3000}'

Sales

GET/v1/salesscope: sales.read
GET/v1/sales/{id}scope: sales.read

Filtros: status, from, to, limit (máx 100), cursor.

Webhooks

GET/v1/webhooksscope: webhooks.manage
POST/v1/webhooksscope: webhooks.manage
PATCH/v1/webhooks/{id}scope: webhooks.manage
DELETE/v1/webhooks/{id}scope: webhooks.manage
POST/v1/webhooks/{id}/testscope: webhooks.manage

Eventos: sale.paid, sale.failed, sale.refunded, sale.chargeback, sale.canceled, subscription.updated, test.ping. Use * para assinar todos.

Verificar assinatura de webhook

Cada entrega inclui o header X-Voren-Signature: t=<timestamp>,v1=<sha256_hex>. Calcule HMAC-SHA256 sobre ${timestamp}.${raw_body} com seu secret e compare em tempo constante. Rejeite entregas com timestamp com mais de 5 minutos.

// Node.js
import { createHmac, timingSafeEqual } from "node:crypto";

function verifyVorenSignature(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
  const timestamp = parts.t;
  const v1 = parts.v1;
  if (!timestamp || !v1) return false;
  if (Math.abs(Date.now()/1000 - Number(timestamp)) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
  const a = Buffer.from(v1, "hex");
  const b = Buffer.from(expected, "hex");
  return a.length === b.length && timingSafeEqual(a, b);
}
Precisa de ajuda? Escreva para api@appvoren.com.br.