NervaNervaAPI Docs
OnlineREST + JSON

Nerva API Documentação

Integre pagamentos PIX na sua plataforma. Gere cobranças, acompanhe pagamentos em tempo real e gerencie saques com poucas linhas de código.

Base URLhttps://pixnerva.com.br/api

1. Autenticação

Todas as requisições autenticadas devem incluir sua API Key no header x-api-key. A chave é gerada no painel do seller em Integrações > API Keys.

Header de autenticação
# Inclua em todas as requisições autenticadas
x-api-key: sk_live_a1b2c3d4e5f6g7h8i9j0...

Segurança: Nunca exponha sua API Key no frontend ou em repositórios públicos. Use variáveis de ambiente no servidor.

2. Criar Cobrança PIX

Cria uma cobrança PIX instantânea. Retorna o código PIX “Copia e Cola” e o QR Code para o pagador. A cobrança expira em 24 horas por padrão (configurável via expirationInSeconds).

POST/sales

Parâmetros do Body

CampoTipoObrigatórioDescrição
amountnumberSIMValor em reais (ex: 100.00). Mínimo R$ 0,01 / Máximo R$ 10.000,00
customerobjectSIMDados do pagador (objeto aninhado — ver campos abaixo)
customer.documentstringSIMCPF ou CNPJ do pagador (único campo obrigatório do customer)
customer.namestringnãoNome completo do pagador
customer.emailstringnãoEmail do pagador
customer.phonestringnãoTelefone do pagador
descriptionstringnãoDescrição da cobrança
itemsarraynãoItens da cobrança [{description, quantity, unitPrice, tangible}]
expirationInSecondsnumbernãoExpiração do PIX em segundos (300–86400, padrão: 86400)
Request
POST /sales
x-api-key: sk_live_...
Content-Type: application/json

{
  "amount": 100.00,
  "description": "Plano Premium",
  "expirationInSeconds": 1800,
  "customer": {
    "name": "João Silva",
    "document": "12345678901",
    "email": "joao@email.com",
    "phone": "11999999999"
  },
  "items": [
    { "description": "Plano Premium", "quantity": 1, "unitPrice": 100.00 }
  ]
}
Response (201)
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "pending",
  "amount": 100.00,
  "fee": 8.98,
  "netAmount": 91.02,
  "pixCode": "00020101021226580014br.gov.bcb...",
  "pixQrCode": "https://pixnerva.com.br/api/...",
  "transactionId": "gw_tx_abc123"
}

Cálculo das taxas: fee = (amount x 6.99%) + R$ 1.99 | netAmount = amount - fee

Exemplo: R$ 100,00 → fee = R$ 8,98 → netAmount = R$ 91,02

Idempotência

Para evitar cobranças duplicadas em caso de retentativa de rede ou timeout, envie o header idempotency-key ao criar uma cobrança. Se a chave já foi processada, a API devolve a resposta original (mesmo PIX, mesmo ID) sem criar nova cobrança.

Recomendado: use o ID interno do pedido no seu sistema (ex: order-12345) ou um UUID v4. A chave é válida por 24 horas — depois disso a mesma chave gera nova cobrança.

Request com idempotency-key
POST /sales
x-api-key: sk_live_...
idempotency-key: pedido-12345
Content-Type: application/json

{
  "amount": 100.00,
  "customer": { "document": "12345678901" }
}

Importante: sempre que sua aplicação retentar uma criação de cobrança após um timeout, mande a MESMA idempotency-key. Sem ela, o seller pode acabar gerando 2 PIX cobrando o mesmo cliente.

Tracking de Marketing

Inclua o objeto tracking no body do POST /sales com UTMs, click IDs e cookies do pixel. Quando a venda for paga, a plataforma dispara automaticamente eventos para a Meta Conversions API e TikTok Events API (se a integração estiver ativa no painel do seller). Tudo opcional.

Campos do objeto tracking

CampoDescrição
utmSourceUTM Source (ex: facebook, google, tiktok)
utmMediumUTM Medium (ex: cpc, social)
utmCampaignUTM Campaign (nome da campanha)
utmContentUTM Content (variação do criativo)
utmTermUTM Term (palavra-chave)
fbclidClick ID do Facebook Ads (query param ?fbclid=...)
ttclidClick ID do TikTok Ads
gclidClick ID do Google Ads
fbpCookie _fbp do Facebook Pixel (browser id)
fbcCookie _fbc do Facebook Pixel (click id)
clientUserAgentUser-Agent do navegador do cliente final
clientIpAddressIP do cliente final
eventIdEvent ID para deduplicar pixel + CAPI (se vazio, derivamos do sale.id)
Exemplo — POST /sales com tracking
{
  "amount": 100.00,
  "customer": { "document": "12345678901" },
  "tracking": {
    "utmSource": "facebook",
    "utmCampaign": "black-friday-2026",
    "fbclid": "IwAR2...",
    "fbp": "fb.1.1700000000000.123456789",
    "fbc": "fb.1.1700000000000.IwAR2...",
    "clientUserAgent": "Mozilla/5.0 (...)",
    "clientIpAddress": "201.10.20.30"
  }
}

Por quê: os browsers bloqueiam cada vez mais o Facebook Pixel, TikTok Pixel e Google Tag. Mandando esses dados pela API, a plataforma envia o evento server-to-server via Meta CAPI / TikTok Events API quando a venda for paga — recuperando atribuição de campanhas que o pixel sozinho perderia.

3. Consultar Cobrança

Retorna os detalhes completos de uma cobrança específica, incluindo o código PIX e o status do pagamento.

GET/sales/:id
Request
GET /sales/a1b2c3d4-e5f6-7890-abcd-ef1234567890
x-api-key: sk_live_...
Response (200)
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "paid",
  "amount": 100.00,
  "fee": 8.98,
  "netAmount": 91.02,
  "description": "Plano Premium",
  "pixCode": "00020101021226580014br.gov.bcb...",
  "pixQrCode": "https://pixnerva.com.br/api/...",
  "payerName": "João Silva",
  "payerEmail": "joao@email.com",
  "payerDocument": "12345678901",
  "payerPhone": "11999999999",
  "paymentMethod": "PIX",
  "transactionId": "gw_tx_abc123",
  "createdAt": "2026-03-23T10: 00: 00Z",
  "updatedAt": "2026-03-23T10: 05: 00Z"
}

Status possíveis: pending paid | failed | refunded | expired

4. Listar Cobranças

Retorna a lista paginada de cobranças da sua empresa, com filtros por status, data e busca.

GET/sales?page=1&limit=20&status=paid

Parâmetros de Query

ParâmetroTipoDescrição
pagenumberPágina (padrão: 1)
limitnumberItens por página (padrão: 20)
statusstringFiltrar: pending, paid, failed, refunded, expired
startDatestringData inicial (ISO 8601)
endDatestringData final (ISO 8601)
searchstringBusca por nome, email ou documento
Response (200)
{
  "data": [
    {
      "id": "a1b2c3d4-...",
      "status": "paid",
      "amount": 100.00,
      "fee": 8.98,
      "netAmount": 91.02,
      "payerName": "João Silva",
      "paymentMethod": "PIX",
      "createdAt": "2026-03-23T10: 00: 00Z"
    }
  ],
  "total": 142,
  "page": 1,
  "limit": 20
}

5. Consultar Saldo

Retorna o saldo total, o valor retido (retenção de segurança) e o saldo disponível para saque.

GET/withdrawals/balance
Request
GET /withdrawals/balance
x-api-key: sk_live_...
Response (200)
{
  "data": {
    "available": 150000,
    "withheld": 7500
  }
}
// Valores em centavos (150000 = R$ 1.500,00)

Retenção: 5% do valor líquido (netAmount) fica retido por 30 dias como proteção contra fraudes. Após o período, o valor é liberado automaticamente.

6. Solicitar Saque

Solicita um saque do saldo disponível. O saque passa por aprovação antes do processamento. Valor mínimo: R$ 10,00.

POST/withdrawals

Parâmetros do Body

CampoTipoObrigatórioDescrição
amountnumberSIMValor do saque em reais
methodstringSIM"pix"
pixKeyTypestringSIMTipo (lowercase): cpf, cnpj, email, phone, random
pixKeystringSIMChave PIX para receber o saque
referencestringnãoID de referência no seu sistema (devolvido nos webhooks)
Request
POST /withdrawals
x-api-key: sk_live_...
Content-Type: application/json

{
  "amount": 500.00,
  "method": "pix",
  "pixKeyType": "cpf",
  "pixKey": "12345678901",
  "reference": "pedido-saque-789"
}
Response (201)
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "amount": 500.00,
  "fee": 0,
  "status": "pending",
  "method": "pix",
  "pixKeyType": "cpf",
  "pixKey": "12345678901",
  "reference": "pedido-saque-789",
  "createdAt": "2026-03-23T14: 30: 00Z"
}

Fluxo: pending approved processing completed | rejected | failed

Listar Saques

Lista os saques da sua conta com filtros e paginação.

GET/withdrawals/my-withdrawals

Query Parameters

CampoTipoDescrição
pagenumberPágina (default: 1)
limitnumberItens por página (máx: 100)
statusstringFiltrar: pending, approved, processing, completed, rejected, failed
Request
GET /withdrawals/my-withdrawals?page=1&limit=20&status=completed
x-api-key: sk_live_...
Response (200)
{
  "data": [
    {
      "id": "a1b2c3d4-...",
      "amount": 500.00,
      "fee": 0,
      "status": "completed",
      "method": "pix",
      "pixKey": "12345678901",
      "reference": "pedido-saque-789",
      "createdAt": "2026-03-23T14: 30: 00Z"
    }
  ],
  "total": 15,
  "page": 1,
  "limit": 20
}

Buscar Saque por ID

Retorna os detalhes de um saque específico pelo ID.

GET/withdrawals/my-withdrawals/:id
Request
GET /withdrawals/my-withdrawals/a1b2c3d4-...
x-api-key: sk_live_...
Response (200)
{
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "amount": 500.00,
    "fee": 0,
    "status": "completed",
    "method": "pix",
    "pixKeyType": "cpf",
    "pixKey": "12345678901",
    "reference": "pedido-saque-789",
    "createdAt": "2026-03-23T14: 30: 00Z",
    "updatedAt": "2026-03-23T14: 35: 00Z"
  }
}

7. Webhooks

Configure uma URL de webhook no painel para receber notificações em tempo real quando o status de um pagamento mudar. A plataforma envia um POST com payload JSON assinado.

Headers enviados pela plataforma

HeaderDescrição
x-pixnerva-timestampTimestamp UNIX do momento do envio
x-pixnerva-signatureAssinatura HMAC-SHA256 do payload
Content-Typeapplication/json

Eventos disponíveis

EventoDescrição
sale.pendingCobrança criada, aguardando pagamento
sale.paidPagamento confirmado
sale.failedPagamento falhou
sale.expiredCobrança expirou sem pagamento
sale.refundedPagamento estornado (total ou parcial)
sale.status_changedQualquer mudança de status (inclui previousStatus no payload)
sale.med_createdContestação MED aberta
sale.med_acceptedContestação aceita (estorno processado)
sale.med_rejectedContestação rejeitada (favorável ao seller)
sale.med_cancelledContestação cancelada pelo cliente

Payload de exemplo (sale.paid)

POST para sua URL de webhook
{
  "event": "sale.paid",
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "paid",
    "amount": 100.00,
    "fee": 8.98,
    "netAmount": 91.02,
    "payerName": "João Silva",
    "payerEmail": "joao@email.com",
    "payerDocument": "12345678901",
    "paymentMethod": "PIX",
    "transactionId": "gw_tx_abc123",
    "createdAt": "2026-03-23T10: 00: 00Z",
    "paidAt": "2026-03-23T10: 02: 30Z"
  }
}

Verificação de assinatura (HMAC-SHA256)

Para garantir que o webhook foi enviado pela plataforma e não foi adulterado, verifique a assinatura HMAC-SHA256 usando o secret do webhook.

  1. Extraia o timestamp e a signature dos headers
  2. Monte a string: timestamp.body (timestamp + ponto + body raw)
  3. Gere o HMAC-SHA256 usando seu secret
  4. Compare o resultado com a signature recebida
  5. Rejeite se o timestamp for maior que 5 minutos (proteção contra replay attack)
Node.js — Verificação de assinatura
const crypto = require("crypto");

function verifyWebhook(req, secret) {
  const timestamp = req.headers["x-pixnerva-timestamp"];
  const signature = req.headers["x-pixnerva-signature"];
  const body = JSON.stringify(req.body);

  // Proteção contra replay attack (5 min)
  const age = Date.now() / 1000 - Number(timestamp);
  if (age > 300) return false;

  // Gerar HMAC e comparar
  const expected = crypto
    .createHmac("sha256", secret)
    .update(timestamp + "." + body)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Retentativas: Se sua URL não responder com status 2xx, a plataforma reenvia automaticamente: 1 min → 5 min → 30 min (máximo 4 tentativas).

8. Códigos de Erro

A API retorna códigos HTTP padrão. Erros incluem um corpo JSON com message e statusCode.

StatusSignificadoQuando ocorre
200SucessoRequisição processada com sucesso
201CriadoRecurso criado com sucesso (venda, saque)
400Dados inválidosCampos obrigatórios ausentes ou formato incorreto
401API Key inválidaChave ausente, expirada ou revogada
403Sem permissãoEmpresa inativa ou sem acesso ao recurso
404Não encontradoRecurso não existe ou pertence a outro seller
429Rate limitMuitas requisições — aguarde e tente novamente
500Erro internoFalha no servidor — contate o suporte
Exemplo de resposta de erro
{
  "message": "Saldo insuficiente para realizar o saque",
  "statusCode": 400
}

9. Exemplos de Código

Exemplos prontos para copiar e colar na sua integração. Substitua sk_live_... pela sua API Key real.

Criar cobrança PIX

curl -X POST https://pixnerva.com.br/api/sales \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk_live_sua_chave_aqui" \
  -d '{
    "amount": 100.00,
    "description": "Plano Premium",
    "customer": {
      "name": "João Silva",
      "document": "12345678901",
      "email": "joao@email.com",
      "phone": "11999999999"
    }
  }'

Consultar saldo

curl -X GET https://pixnerva.com.br/api/withdrawals/balance \
  -H "x-api-key: sk_live_sua_chave_aqui"

Verificar assinatura do webhook

const crypto = require("crypto");

// Middleware Express para verificar webhook
function verifyWebhook(req, res, next) {
  const secret = process.env.WEBHOOK_SECRET;
  const timestamp = req.headers["x-pixnerva-timestamp"];
  const signature = req.headers["x-pixnerva-signature"];
  const body = JSON.stringify(req.body);

  // Proteção contra replay (5 min)
  const age = Date.now() / 1000 - Number(timestamp);
  if (age > 300) {
    return res.status(401).json({ error: "Timestamp expirado" });
  }

  const expected = crypto
    .createHmac("sha256", secret)
    .update(timestamp + "." + body)
    .digest("hex");

  const valid = crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );

  if (!valid) {
    return res.status(401).json({ error: "Assinatura inválida" });
  }

  next();
}

// Uso
app.post("/webhooks/payment", verifyWebhook, (req, res) => {
  const { event, data } = req.body;

  if (event === "sale.paid") {
    console.log("Pagamento confirmado:", data.id);
    // Liberar produto/serviço para o cliente
  }

  res.status(200).json({ received: true });
});