A API da PixGo é um REST simples, sem SDK, sem dependência exótica. Se você sabe fazer um POST em HTTP, você integra. Esse guia cobre todo o fluxo: gerar chave, criar pagamento, receber webhook, validar assinatura — com exemplos de código pra copiar e colar.

Em resumo
  • Base URL: https://pixgo.org/api/v1
  • Auth: header X-API-Key: pk_... (gera em Minha Loja)
  • 3 endpoints principais: POST /payment/create, GET /payment/{id}, GET /payment/{id}/status
  • Webhooks: 4 eventos (order.created, payment.completed, payment.expired, payment.refunded) com HMAC-SHA256
  • Rate limit: 10.000 req/24h default, 1.000 req/24h só no endpoint de status
  • Sem sandbox: toda chave é produção. Teste com valores pequenos.

Gerando sua API Key

  1. Acesse o menu API Keys (pixgo.org/api-keys)
  2. Clique em Solicitar acesso e conclua a validação pedida na tela
  3. Com o acesso aprovado, a chave aparece na mesma página (campo API Key)
  4. Copie a chave (formato pk_ + sequência aleatória) e guarde em local seguro
Cuidados com a chave:
  • É uma chave por usuário — gerar nova invalida a anterior automaticamente
  • NÃO pode editar/renomear — só substituir
  • Guarde em variável de ambiente (.env, secrets manager) — nunca no código versionado
  • É chave de produção — toda chamada cobra/recebe de verdade
  • Se vazar, gere uma nova IMEDIATAMENTE (a antiga para de funcionar)

Integre cobranças Pix ao seu sistema com API e webhooks. Conheça a API Pix da PixGo.

Criar conta

Endpoint 1 — Criar pagamento

É o endpoint que você usa pra gerar um QR Code de cobrança. Tudo começa por aqui.

POST https://pixgo.org/api/v1/payment/create
Headers:
  X-API-Key: pk_sua_chave_aqui
  Content-Type: application/json

Body (JSON):
{
  "amount": 100.00,
  "description": "Produto X - SKU 123",
  "external_id": "pedido_42",
  "receiver_name": "Maria Silva",
  "receiver_cpf": "12345678900",
  "receiver_email": "[email protected]",
  "receiver_phone": "11999998888",
  "webhook_url": "https://seusite.com/webhooks/pixgo"
}

Campos do request

Campo Tipo Obrigatório Descrição
amountnumberSimValor em Reais. Mín R$10, máx conforme seu nível
descriptionstringNãoAparece no comprovante do pagador
external_idstringNãoSeu ID interno do pedido — volta no webhook
receiver_namestringNãoNome do cliente — volta no webhook
receiver_cpfstringSimCPF ou CNPJ do pagador, somente números (11 ou 14 dígitos). Sem ele a cobrança é recusada com 422 PAYER_DOC_REQUIRED
receiver_emailstringNãoE-mail do cliente
receiver_phonestringNãoTelefone do cliente
webhook_urlstringNãoURL específica desse pagamento (sobrescreve a global)

Resposta de sucesso (201)

{
  "success": true,
  "data": {
    "payment_id": "019c8b9149ec7433a5065b834cb45ccc",
    "external_id": "pedido_42",
    "amount": 100.00,
    "status": "pending",
    "qr_code": "00020126360014BR.GOV.BCB.PIX...",
    "qr_image_url": "https://pixgo.org/qr/019c8b9149ec...png",
    "expires_at": "2026-05-15T14:30:00-03:00",
    "created_at": "2026-05-15T14:00:00-03:00"
  }
}

O campo qr_code é o Copia-e-Cola (BR Code, formato EMV). O qr_image_url é uma URL pública pra exibir a imagem do QR Code.

Importante: guarde o payment_id no seu banco de dados, vinculado ao seu external_id. É com ele que você vai consultar status depois e conferir os webhooks.

Respostas de erro

Todo erro devolve success: false, um código estável em error e um texto em message. Trate pelo error — o texto do message pode mudar.

{
  "success": false,
  "error": "PAYER_DOC_REQUIRED",
  "message": "Envie o campo receiver_cpf com o CPF ou CNPJ do pagador (somente números)."
}
HTTP error O que fazer
401MISSING_API_KEYHeader X-API-Key ausente
401INVALID_API_KEYChave inexistente ou desativada
400VALIDATION_ERRORCampo obrigatório ausente ou valor fora do formato
400invalid_webhook_urlUse HTTPS com domínio ou IP público — localhost, 127.0.0.1 e IPs privados são recusados
422PAYER_DOC_REQUIREDEnvie receiver_cpf com o CPF ou CNPJ do pagador. Obrigatório em qualquer valor
422PAYER_BLOCKEDDocumento do pagador reprovado na checagem antifraude. Peça outro CPF/CNPJ — repetir a chamada não resolve
422PAYER_COMPLIANCE_BLOCKEDMesma coisa, barrado na camada de compliance
400LIMIT_EXCEEDEDValor acima do limite do seu nível
429PAYER_RATE_LIMITMuitas cobranças para o mesmo documento na última hora
429RATE_LIMIT_EXCEEDEDLimite da sua chave estourado — respeite o Retry-After
503PROVIDER_UNAVAILABLEParceiro bancário fora no momento. É transitório: tente de novo depois do Retry-After (120s)
Mudança importante: o receiver_cpf passou a ser obrigatório em qualquer valor. Se a sua integração não enviava esse campo, ela vai receber 422 PAYER_DOC_REQUIRED até passar a enviar. Aceita CPF (11 dígitos) ou CNPJ (14), somente números — pontuação é ignorada.

Endpoint 2 — Detalhes do pagamento

Retorna o objeto completo do pagamento — útil pra reconciliação batch ou pra mostrar status detalhado pro cliente.

GET https://pixgo.org/api/v1/payment/{id}
Headers:
  X-API-Key: pk_sua_chave_aqui

Resposta inclui todos os campos do create + dados pós-pagamento (data, breakdown de taxas, dados do pagador mascarados). Esse é o endpoint com rate limit padrão (10.000 req/24h).

Endpoint 3 — Status do pagamento

Versão enxuta do endpoint anterior — retorna só o status atual + alguns campos básicos. Pensado pra polling rápido (você consulta a cada N segundos enquanto o cliente está na tela do PIX).

GET https://pixgo.org/api/v1/payment/{id}/status
Headers:
  X-API-Key: pk_sua_chave_aqui

Response:
{
  "success": true,
  "data": {
    "payment_id": "019c8b91...",
    "external_id": "pedido_42",
    "amount": 100.00,
    "status": "completed",
    "customer_name": "Maria Silva",
    "customer_cpf": "***.***.***-00",
    "customer_phone": "***988",
    "created_at": "2026-05-15T14:00:00-03:00",
    "updated_at": "2026-05-15T14:25:30-03:00"
  }
}
Atenção — rate limit menor: esse endpoint tem cap de 1.000 req/24h por chave. É 10× menor que o /payment/{id}. Use polling com intervalo razoável (a cada 3-5 segundos, não a cada 100ms). Pra confirmação confiável, prefira webhook em vez de polling intenso.

Webhooks — o caminho recomendado

Webhooks são notificações HTTP que a PixGo envia automaticamente pro seu servidor quando o pagamento muda de status. É mais eficiente que ficar fazendo polling.

Fluxo de webhook: servidor PixGo envia notificação assinada com HMAC pro seu servidor
Servidor PixGo envia evento → assinado com HMAC-SHA256 → seu servidor recebe, valida e processa.

Configuração

Dois lugares onde você define a URL de webhook:

  • Global (Minha Loja): URL única que recebe TODOS os eventos da sua conta. Configure em pixgo.org/minha-loja → Webhook.
  • Por pagamento: passe webhook_url no body do POST /payment/create. Sobrescreve a global só pra esse pagamento.

Eventos disponíveis

Evento Disparado quando
order.createdPagamento foi criado (logo após o POST /payment/create)
payment.completedPIX foi confirmado (status mudou pra completed)
payment.expiredQR expirou sem pagamento (20min QR avulso, 30min Cobranças)
payment.refundedPagamento foi estornado em definitivo (MED veredito contra ou estorno voluntário)

Headers que a PixGo envia

POST /seu-endpoint
X-Webhook-Event: payment.completed
X-Webhook-Signature: a3f5...c4d (HMAC-SHA256)
X-Webhook-Timestamp: 1715789430
Content-Type: application/json

Payload enriquecido — estrutura completa

Cada webhook envia um JSON com até 5 objetos. Aqui o exemplo de payment.completed:

{
  "event": "payment.completed",
  "payment_id": "019c8b91...",
  "external_id": "pedido_42",
  "amount": 100.00,
  "completed_at": "2026-05-15T14:25:30-03:00",

  "customer": {
    "name": "Maria Silva",
    "cpf": "12345678900",
    "email": "[email protected]",
    "phone": "11999998888",
    "address": "...",
    "custom_field": "campanha_outubro"
  },

  "payer": {
    "name": "Maria",
    "cpf": "***.***.789-00"
  },

  "product": {
    "business_name": "Minha Loja",
    "description": "Produto X - SKU 123",
    "value": 100.00
  },

  "amounts": {
    "gross": 100.00,
    "fee_pixgo": 2.00,
    "fee_liquid": 0.50,
    "fee_total": 2.50,
    "net": 97.50,
    "currency": "BRL"
  }
}

O que cada objeto significa

  • customer — dados que o cliente preencheu no checkout (ou que você passou no POST /payment/create). Use pra CRM, etiqueta de envio, recibo.
  • payer — dados de quem efetivamente pagou o PIX (recebidos do banco). Geralmente igual ao customer, mas pode diferir (ex: marido paga pelo CPF da esposa). CPF vem mascarado por LGPD.
  • product — dados da loja/cobrança no momento da criação.
  • amounts — breakdown completo das taxas e o líquido que vai cair na sua carteira. Mais detalhes no artigo Taxas da PixGo.

Validando a assinatura HMAC

Toda webhook vem assinado pra você ter certeza que é a PixGo enviando, não um malicioso falsificando. Valide sempre.

Lógica da assinatura

  1. Pegue o cabeçalho X-Webhook-Timestamp e o body bruto (raw) da request
  2. Concatene: timestamp + "." + body_raw
  3. Calcule HMAC-SHA256 dessa string usando o seu Webhook Secret (começa com whsec_ e aparece na página API Keys) como segredo
  4. Compare com o valor de X-Webhook-Signature
  5. Se bater → autêntico. Se não → rejeite (HTTP 401 ou 400).

Exemplo em PHP

<?php
$secret = 'whsec_seu_webhook_secret_aqui';
$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$received_sig = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';

$payload = $timestamp . '.' . $body;
$expected_sig = hash_hmac('sha256', $payload, $secret);

if (!hash_equals($expected_sig, $received_sig)) {
    http_response_code(401);
    exit('Invalid signature');
}

// OK, processa o evento
$data = json_decode($body, true);
if ($data['event'] === 'payment.completed') {
    // ... sua lógica
}
http_response_code(200);
echo 'OK';

Exemplo em Python (Flask)

import hmac, hashlib
from flask import request, abort

SECRET = b'whsec_seu_webhook_secret_aqui'

@app.route('/webhooks/pixgo', methods=['POST'])
def webhook():
    body = request.get_data()
    timestamp = request.headers.get('X-Webhook-Timestamp', '')
    received = request.headers.get('X-Webhook-Signature', '')

    payload = f'{timestamp}.{body.decode()}'.encode()
    expected = hmac.new(SECRET, payload, hashlib.sha256).hexdigest()

    if not hmac.compare_digest(expected, received):
        abort(401)

    data = request.get_json()
    if data['event'] == 'payment.completed':
        # ... sua lógica
        pass
    return 'OK', 200

Exemplo em Node.js (Express)

const crypto = require('crypto');
const express = require('express');
const app = express();

const SECRET = 'whsec_seu_webhook_secret_aqui';

app.post('/webhooks/pixgo',
    express.raw({type: 'application/json'}),
    (req, res) => {
        const body = req.body.toString();
        const ts = req.header('X-Webhook-Timestamp') || '';
        const received = req.header('X-Webhook-Signature') || '';

        const expected = crypto
            .createHmac('sha256', SECRET)
            .update(`${ts}.${body}`)
            .digest('hex');

        if (expected !== received) return res.status(401).send('Invalid');

        const data = JSON.parse(body);
        if (data.event === 'payment.completed') {
            // ... sua lógica
        }
        res.send('OK');
    }
);

Rate Limits — o que importa saber

Endpoint Limite Dica
POST /payment/create10.000 req/24hMais que suficiente pra uso normal
GET /payment/{id}10.000 req/24hUse pra reconciliação batch
GET /payment/{id}/status1.000 req/24hLimitado — prefira webhook

Esses valores são padrão pra todas as contas. Se você precisa de mais, abra chamado em pixgo.org/chamados explicando o caso — não é self-service.

Boa prática: nunca confie em polling como único caminho. Configure webhook + endpoint de status como fallback. Webhook resolve 99% dos casos; o status só pra confirmar quando o usuário fica refresh-andando a tela.

Boas práticas pra integração robusta

  • Idempotência: webhooks podem ser entregues mais de uma vez (em caso de retry). Use o payment_id + event como chave única no seu banco pra ignorar duplicados.
  • Responda 2xx rapidamente: receba o webhook, valide assinatura, enfileire o processamento pesado (queue/job) e responda 200. Não trave o webhook fazendo trabalho síncrono longo (vai dar timeout e a PixGo retenta).
  • Armazene o external_id: passe seu próprio ID interno no POST /payment/create. Volta em todo webhook — facilita reconciliar com seu pedido.
  • Trate payment.refunded obrigatoriamente: estorno acontece (MED, ou você mesmo pediu). Se ignorar o evento, sua contabilidade fica errada.
  • Não confie só no front-end: ao receber confirmação na tela do cliente via polling, valide com webhook server-side antes de liberar produto digital. Front pode ser manipulado.
  • Logue tudo: salve cada webhook recebido + assinatura + status do processamento. Se der problema, é o que vai te salvar.
  • Configure retry no seu webhook: PixGo retenta em caso de 5xx, mas se você responder 200 e depois falhar no processamento, perdeu. Tenha sua própria fila com retry interno.

WordPress, WooCommerce, plugins prontos?

Hoje a PixGo não tem plugin oficial pra nenhuma plataforma. A integração é sempre via API REST. Como a API é simples, qualquer dev consegue plugar em poucas horas:

  • WordPress / WooCommerce: implementação via plugin custom — você escreve um payment gateway que chama nossa API no process_payment e recebe webhook em URL própria.
  • Shopify: usa Shopify Apps com webhook próprio — mesma estrutura.
  • Magento, OpenCart, PrestaShop: módulo custom seguindo o padrão de cada plataforma.
  • SaaS personalizado: integração direta no seu backend, mais simples ainda.

Recorrência (assinatura)

A API atual não tem endpoint nativo de recorrência (tipo "criar assinatura mensal automática"). O caminho hoje é:

  1. No seu sistema, você mantém a lista de clientes ativos e o ciclo de cobrança
  2. Em cada vencimento, sua rotina chama POST /payment/create com o valor do cliente
  3. Cliente paga (ou não) cada cobrança individualmente — a PixGo não faz débito automático
  4. Se ele paga, você processa o webhook payment.completed e renova o ciclo
  5. Se não paga, você decide a regra (notificar, suspender, dar carência)

A PixGo tem também um módulo de cobrança recorrente Pix que faz isso pra quem prefere usar a interface pronta sem programar — vale conferir antes de implementar do zero.

FAQ pra desenvolvedores

Tem sandbox / ambiente de teste?

Não. Toda chave é produção. Pra testar, use valores pequenos (R$10-R$15) e pague do seu próprio CPF — depois faça swap dentro da PixGo Wallet se quiser recuperar.

Posso filtrar pagamentos por external_id?

Sim. Use GET /api/v1/payments?external_id=SEU_ID com a sua X-API-Key: a resposta traz a lista de pagamentos com esse external_id (até 50 caracteres) e volta vazia se não houver nenhum. Mesmo assim, guarde o payment_id no seu banco no momento do create, porque é ele que identifica cada cobrança nos webhooks.

O webhook tem retry automático?

Sim. Se sua URL responder 5xx ou der timeout, a PixGo retenta com backoff exponencial por algumas horas. Se mesmo assim falhar, eventualmente desiste. Por isso responda 2xx rápido (mesmo que processe assíncrono).

Posso usar a mesma chave em múltiplos servidores?

Sim. A chave não tem limite de origens. Mas vale lembrar do rate limit (cumulativo entre todos os servidores que usam a mesma chave).

Tem CORS habilitado? Posso chamar a API do front-end?

NÃO chame a API do front-end. Sua chave nunca pode ir parar no JavaScript do navegador. Use sempre seu backend como intermediário. CORS não é o problema — segurança da chave é.

Posso testar webhook localmente?

Sim, usando túneis (ngrok, localtunnel, Cloudflare Tunnel). Cria um túnel pro seu localhost, registra essa URL no webhook_url do pagamento de teste, e a PixGo manda direto pro seu servidor local.

Qual o timeout do webhook?

Você tem ~10 segundos pra responder 2xx. Se demorar mais, considera falha e retenta.

Tem SDK em alguma linguagem?

Não. A API é REST simples — qualquer cliente HTTP serve. Não temos SDK oficial em Node/Python/PHP/Go. Comunidade pode ter wrappers — mas não são oficiais e podem estar desatualizados.

O external_id precisa ser único?

Não é validado pela PixGo. Você pode até repetir, mas vai dificultar reconciliação do seu lado. Recomendado: uso UUIDs ou IDs auto-incrementais.

Pode passar custom_field com JSON?

O campo é uma string. Você pode passar JSON serializado ('{"tag":"out2026"}') — sua aplicação faz parse depois. Sem limite duro de tamanho, mas mantenha curto (alguns KB).


Resumo prático

  • API REST simples — Base https://pixgo.org/api/v1 + header X-API-Key
  • 3 endpoints principais: criar, detalhar, status
  • Webhooks com 4 eventos + HMAC-SHA256 (valide SEMPRE)
  • Rate limit: 10k/24h geral, 1k/24h só no /status
  • Sem SDK / sem sandbox — toda chave é produção
  • Sem plugin oficial — integração custom em WP, Shopify, etc
  • Recorrência: rotina externa chamando /create no vencimento
  • Documentação live: pixgo.org/api/v1/docs

Leituras relacionadas: Taxas e breakdown amounts · Limites por nível · Tratamento de MED na sua integração