PSPixPSPix
Documentação
API v1
Acessar Painel
Exemplos em:
PIX em tempo real
Gere QR Codes e receba confirmações instantâneas do Banco Central.
Webhooks assinados
HMAC-SHA256 em todo evento — valide antes de processar.
API REST simples
HTTP Basic Auth, JSON puro, sem SDK obrigatório.

Introdução

A API PSPix permite criar cobranças PIX, consultar transações, gerenciar saques e configurar notificações em tempo real via webhook. Todos os endpoints retornam JSON.

Base URLhttps://api.pspix.com.br
Versãov1
Formatoapplication/json
AutenticaçãoHTTP Basic Auth
SegurançaTLS 1.2+ obrigatório

Quickstart

Node.js
import crypto from "node:crypto";

const res = await fetch("https://api.pspix.com.br/v1/charges", {
  method: "POST",
  headers: {
    "Authorization": `Basic ${auth}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    amount: 15000,                    // R$ 150,00
    external_reference: "pedido-4521",
    description: "Compra Loja XYZ",
    expires_in: 3600,
    payer: {
      name: "João Silva",
      document: "12345678900",
      email: "joao@email.com",
    },
  }),
});

const charge = await res.json();
// charge.pix.qr_code_image → base64 do QR Code PNG
console.log(charge.pix.qr_code_image);

Autenticação

Toda requisição deve incluir o header Authorization com suas credenciais em Base64 (padrão HTTP Basic Auth).

CampoTipoReq.Descrição
client_idstringIdentificador público (ex: wp_prod_a1b2c3)
client_secretstringChave secreta — exibida apenas na criação
Acesse Painel → Configurações → Credenciais para gerar suas chaves. O client_secret só é exibido uma vez — copie imediatamente.
Node.js
// Todas as requisições usam HTTP Basic Auth
const auth = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString("base64");

const res = await fetch("https://api.pspix.com.br/v1/charges", {
  headers: {
    "Authorization": `Basic ${auth}`,
    "Content-Type": "application/json",
  },
});

Idempotência

Toda criação de cobrança deve enviar o header Idempotency-Key com um UUID v4 único por transação.

Ao reenviar com o mesmo key (ex: após timeout de rede), a API retorna a cobrança original sem criar duplicata.

Gere o UUID antes de chamar a API e salve-o junto ao pedido. Nunca reutilize o mesmo key para pedidos distintos.
Resposta JSON
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

// Reenviar com o mesmo key → retorna a cobrança original
// Reenviar com key diferente → cria nova cobrança

Erros

Todas as respostas de erro seguem o mesmo formato JSON com message descritivo.

HTTPQuando ocorre
400Dados inválidos na requisição
401Credenciais ausentes ou inválidas
404Recurso não encontrado
422Regra de negócio violada
429Rate limit excedido — aguarde antes de tentar novamente
502Erro no banco parceiro — tente novamente
500Erro interno — tente novamente
Resposta JSON
// Formato padrão de erro
{
  "message": "amount must be greater than zero"
}

// Exemplo 422 — regra de negócio
{
  "message": "withdrawal amount (100) must be greater than fee (350)"
}

Criar cobrança PIX

POST/v1/charges

Cria uma nova cobrança PIX e retorna o QR Code pronto para exibição. Requer header Idempotency-Key.

CampoTipoReq.Descrição
amountintegerValor em centavos (15000 = R$ 150,00)
external_referencestringID do pedido no seu sistema
descriptionstringAparece no extrato do pagador
expires_inintegerValidade em segundos (padrão: 3600)
payer.namestringNome completo do pagador
payer.documentstringCPF ou CNPJ (somente dígitos)
payer.emailstringE-mail do pagador

Status possíveis

PENDING Aguardando pagamento
PAID Pago
EXPIRED Expirado
REFUNDED Estornado
Node.js
import crypto from "node:crypto";

const res = await fetch("https://api.pspix.com.br/v1/charges", {
  method: "POST",
  headers: {
    "Authorization": `Basic ${auth}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    amount: 15000,                    // R$ 150,00
    external_reference: "pedido-4521",
    description: "Compra Loja XYZ",
    expires_in: 3600,
    payer: {
      name: "João Silva",
      document: "12345678900",
      email: "joao@email.com",
    },
  }),
});

const charge = await res.json();
// charge.pix.qr_code_image → base64 do QR Code PNG
console.log(charge.pix.qr_code_image);
Resposta JSON
// 201 Created
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "PENDING",
  "amount": 15000,
  "pix": {
    "qr_code": "00020126580014br.gov.bcb.pix...",
    "qr_code_image": "data:image/png;base64,...",
    "txid": "abc123def456",
    "expires_at": "2024-01-15T15:00:00Z"
  }
}

Consultar cobrança

GET/v1/charges/{id}

Retorna os dados atualizados de uma cobrança específica. Use para verificar status após o pagamento.

Node.js
const res = await fetch(
  `https://api.pspix.com.br/v1/charges/${chargeId}`,
  { headers: { "Authorization": `Basic ${auth}` } }
);
const charge = await res.json();
console.log(charge.status); // "PAID" | "PENDING" | ...
Resposta JSON
// 200 OK
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "PAID",
  "amount": 15000,
  "external_ref": "pedido-4521",
  "paid_at": "2024-01-15T14:35:22Z"
}

Listar cobranças

GET/v1/charges
CampoTipoReq.Descrição
pageintegerPágina (padrão: 1)
per_pageintegerItens por página — máx. 100 (padrão: 20)
statusstringFiltro: PENDING | PAID | EXPIRED | REFUNDED
Node.js
const params = new URLSearchParams({
  page: "1", per_page: "20", status: "PAID",
});
const res = await fetch(
  `https://api.pspix.com.br/v1/charges?${params}`,
  { headers: { "Authorization": `Basic ${auth}` } }
);
const { data, meta } = await res.json();
Resposta JSON
// 200 OK
{
  "data": [
    { "id": "550e8400-...", "status": "PAID", "amount": 15000, ... },
    { "id": "a1b2c3d4-...", "status": "PENDING", "amount": 5000, ... }
  ],
  "meta": { "page": 1, "per_page": 20 }
}

Consultar saldo

GET/v1/balance

Retorna o saldo em tempo real da sua conta.

CampoDescrição
available_centsSaldo disponível para saque
blocked_centsTransações ainda não confirmadas (PENDING/PROCESSING)
withdrawn_centsTotal já sacado (status APPROVED)
Node.js
const res = await fetch("https://api.pspix.com.br/v1/balance", {
  headers: { "Authorization": `Basic ${auth}` },
});
const { available_cents, blocked_cents, withdrawn_cents } = await res.json();

// Converter centavos → reais
const toReais = (c) => (c / 100).toLocaleString("pt-BR", {
  style: "currency", currency: "BRL",
});
console.log("Disponível:", toReais(available_cents));
Resposta JSON
// 200 OK
{
  "available_cents": 125000,
  "blocked_cents":     30000,
  "withdrawn_cents":   50000
}
// available_cents = 125000 → R$ 1.250,00 disponíveis

Solicitar saque

POST/v1/withdrawals

Solicita uma transferência PIX do saldo disponível para uma conta bancária cadastrada. O valor líquido já desconta a taxa da plataforma.

CampoTipoReq.Descrição
bank_account_idstring (UUID)ID da conta em Painel → Bancos
amount_centsintegerValor bruto em centavos — deve ser maior que a taxa

Status possíveis

PENDINGAguardando envio ao banco
PROCESSINGEnviado — aguardando confirmação
APPROVEDConcluído — dinheiro na conta
FAILEDFalhou — saldo restaurado
Node.js
const res = await fetch("https://api.pspix.com.br/v1/withdrawals", {
  method: "POST",
  headers: {
    "Authorization": `Basic ${auth}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    bank_account_id: "7f3b2a1c-4a9d-4c2e-b8f1-3d9e2a1b5c6d",
    amount_cents: 50000,   // R$ 500,00 bruto
  }),
});
const withdrawal = await res.json();
// withdrawal.net_cents = valor líquido após taxa
Resposta JSON
// 201 Created
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "PROCESSING",
  "amount_cents": 50000,
  "fee_cents":     350,
  "net_cents":    49650,
  "provider_tx_id": "abc123xyz"
}

Listar saques

GET/v1/withdrawals
GET/v1/withdrawals/{id}
CampoTipoReq.Descrição
pageintegerPágina (padrão: 1)
per_pageintegerItens por página — máx. 100 (padrão: 20)
Resposta JSON
// GET /v1/withdrawals — 200 OK
{
  "data": [
    {
      "id": "a1b2c3d4-...",
      "status": "APPROVED",
      "amount_cents": 50000,
      "fee_cents": 350,
      "net_cents": 49650,
      "created_at": "2024-01-15T10:00:00Z"
    }
  ],
  "meta": { "page": 1, "per_page": 20 }
}

Configurar webhook

GET/v1/webhook
PUT/v1/webhook

Configure a URL que receberá eventos em tempo real. Também é possível configurar pelo Painel em Configurações → Webhooks.

CampoTipoReq.Descrição
endpoint_urlstringURL HTTPS que receberá os eventos (POST)
eventsstring[]Lista de eventos para assinar
secretstringSegredo HMAC — se omitido, gerado automaticamente
O secret retornado é exibido apenas uma vez. Guarde-o imediatamente — use-o para validar a assinatura de todos os webhooks recebidos.
Node.js
// 1. Configurar endpoint de webhook
const res = await fetch("https://api.pspix.com.br/v1/webhook", {
  method: "PUT",
  headers: {
    "Authorization": `Basic ${auth}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    endpoint_url: "https://meusite.com.br/webhooks/pspix",
    events: [
      "transaction.paid",
      "transaction.refunded",
      "withdrawal.paid",
      "withdrawal.failed",
    ],
    // secret omitido → gerado automaticamente
  }),
});
const { secret } = await res.json();
// ⚠️  Guarde o secret — necessário para validar webhooks
Resposta JSON
// PUT /v1/webhook — 200 OK
{
  "endpoint_url": "https://meusite.com.br/webhooks/pspix",
  "events": ["transaction.paid", "transaction.refunded", "withdrawal.paid"],
  "secret": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "active": true
}

Eventos disponíveis

EventoQuando
transaction.paidPIX confirmado pelo Banco Central
transaction.refundedEstorno processado
withdrawal.paidSaque aprovado — dinheiro na conta
withdrawal.failedSaque falhou — saldo restaurado
Resposta JSON
// Payload recebido no seu endpoint
{
  "event_type":     "transaction.paid",
  "company_id":     "uuid-da-empresa",
  "transaction_id": "550e8400-e29b-41d4-a716-446655440000",
  "amount":         15000,
  "net_amount":     14610,
  "timestamp":      "2024-01-15T14:35:22Z"
}

// Headers incluídos
X-PSPix-Signature: sha256=<hmac_hex>
X-PSPix-Event:     transaction.paid

Verificar assinatura

Cada webhook inclui o header X-PSPix-Signature com assinatura HMAC-SHA256 do body. Valide sempre antes de processar.

Como funciona
1Receba o request com body bruto (raw bytes — não faça JSON.parse antes)
2Leia o header X-PSPix-Signature
3Compute: "sha256=" + HMAC-SHA256(body, secret)
4Compare com timingSafeEqual para evitar timing attacks
5Processe o evento e responda HTTP 200
Responda HTTP 200 para confirmar o recebimento. Qualquer outro status aciona reenvios automáticos — até 5 tentativas com backoff exponencial.
Node.js
import crypto from "node:crypto";
import express from "express";

const WEBHOOK_SECRET = process.env.PSPIX_WEBHOOK_SECRET;

app.post(
  "/webhooks/pspix",
  express.raw({ type: "application/json" }), // raw buffer — não fazer parse antes!
  (req, res) => {
    const signature = req.headers["x-pspix-signature"] ?? "";
    const expected  = "sha256=" + crypto
      .createHmac("sha256", WEBHOOK_SECRET)
      .update(req.body)
      .digest("hex");

    if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
      return res.status(401).json({ error: "Invalid signature" });
    }

    const event = JSON.parse(req.body.toString());

    switch (event.event_type) {
      case "transaction.paid":
        await fulfillOrder(event.transaction_id, event.amount);
        break;
      case "withdrawal.paid":
        await notifyWithdrawalDone(event.transaction_id);
        break;
    }

    res.sendStatus(200); // ← obrigatório confirmar!
  }
);

PSPix© 2026 PSPix · Gateway de Pagamentos PIX
contato@pspix.com.br