Skip to main content
Tutorial para montar um recuperador de vendas (carrinho abandonado, PIX não pago, boleto vencido) usando a API pública v1. Você vai listar cobranças pendentes, pegar nome, e-mail e telefone do comprador e disparar follow-up no seu CRM, WhatsApp ou e-mail transacional.

Visão geral

O extrato da conta expõe o objeto payer com os dados preenchidos no checkout do link de pagamento — os mesmos que você vê no extrato da dashboard.
Campo em payerUso na recuperação
namePersonalizar mensagem
emailE-mail transacional
phoneWhatsApp / SMS
documentIdentificar cliente recorrente
Após o pagamento PIX confirmado, name e document passam a refletir o comprovante bancário. email e phone continuam vindo do checkout do link quando disponíveis.

Permissões necessárias

PermissãoPara quê
account/transactionsListar cobranças e ler payer
webhooks/createOpcional — parar recuperação quando payment.paid chegar
Chave com preset read já inclui account/transactions. Detalhes: Permissões da API key.

1. Listar cobranças candidatas à recuperação

O endpoint principal é o extrato da conta. Filtre entradas pendentes criadas nas últimas horas:
curl -G 'https://api.goatpay.com.br/v1/account/transactions' \
  -H 'X-API-Key: gp_live_SUA_CHAVE' \
  --data-urlencode 'status=PENDING' \
  --data-urlencode 'type=entrada' \
  --data-urlencode 'method=PIX' \
  --data-urlencode 'page=1' \
  --data-urlencode 'pageSize=50' \
  --data-urlencode 'dateFrom=2026-06-24T00:00:00.000Z'

Filtros úteis

QueryRecuperação de…
status=PENDINGPIX/boleto ainda não pagos
status=CANCELED + janela curtaQR PIX expirado (reenviar link)
type=entradaSó recebimentos (ignora saques)
method=PIX / Boleto / CartãoCanal específico
externalReference=pedido-42Pedido pontual no seu sistema
merchantSubaccountId=clx_subExtrato de uma subconta
Paginação: incremente page até page > pages. Máximo pageSize=100.

2. Ler os dados do cliente em cada item

Exemplo de item retornado (campos relevantes):
{
  "id": "clx_pix_in",
  "type": "PIX_IN",
  "status": "PENDING",
  "amount": 97.0,
  "description": "Curso Avançado",
  "externalReference": "pedido-1042",
  "qrcodeUrl": "https://pay.goatpay.com.br/p/clx_pix_in",
  "expiresAt": "2026-06-24T23:59:59.000Z",
  "createdAt": "2026-06-24T18:00:00.000Z",
  "payer": {
    "name": "Maria Souza",
    "document": "52998224725",
    "email": "maria@email.com",
    "phone": "11999998888"
  }
}
Regras práticas:
  • Sem payer ou sem contato — cobrança criada direto na API sem checkout de link; não dá para recuperar por e-mail/WhatsApp via extrato.
  • payer.email ou payer.phone — suficiente para disparar follow-up.
  • externalReference — chave para cruzar com pedido no seu banco.
  • id — chave única da transação GoatPay (use para deduplicar).
  • qrcodeUrl — link do checkout para reenviar na mensagem.
Documentação completa do extrato

3. Script de exemplo (Node.js)

Job agendado (cron a cada 15–30 min) que monta a fila de recuperação:
const API_KEY = process.env.GOATPAY_API_KEY!;
const BASE = "https://api.goatpay.com.br/v1";

type Tx = {
  id: string;
  status: string;
  amount: number;
  description: string | null;
  externalReference: string | null;
  qrcodeUrl?: string;
  expiresAt?: string | null;
  createdAt: string;
  payer?: {
    name?: string | null;
    document?: string | null;
    email?: string | null;
    phone?: string | null;
  };
};

async function listPendingPix(sinceIso: string): Promise<Tx[]> {
  const items: Tx[] = [];
  let page = 1;

  while (true) {
    const qs = new URLSearchParams({
      status: "PENDING",
      type: "entrada",
      method: "PIX",
      page: String(page),
      pageSize: "100",
      dateFrom: sinceIso,
    });

    const res = await fetch(`${BASE}/account/transactions?${qs}`, {
      headers: { "X-API-Key": API_KEY },
    });
    const body = await res.json();
    if (!body.success) throw new Error(body.message);

    items.push(...body.data.items);
    if (page >= body.data.pages) break;
    page += 1;
  }

  return items;
}

function isRecoverable(tx: Tx): boolean {
  const email = tx.payer?.email?.trim();
  const phone = tx.payer?.phone?.trim();
  return Boolean(email || phone);
}

async function main() {
  const since = new Date(Date.now() - 48 * 60 * 60 * 1000).toISOString();
  const pending = await listPendingPix(since);

  for (const tx of pending.filter(isRecoverable)) {
    // Evite reenviar: consulte seu banco se já recuperou este tx.id
    const contact = tx.payer!.email?.trim() || tx.payer!.phone!.trim();
    console.log("Recuperar", {
      transactionId: tx.id,
      reference: tx.externalReference,
      contact,
      amount: tx.amount,
      checkoutUrl: tx.qrcodeUrl,
    });
    // await sendWhatsApp(...) ou await sendEmail(...)
  }
}

main().catch(console.error);
Respeite o rate limit (100 req/min). Prefira uma listagem paginada a cada 15–30 min em vez de polling contínuo.

4. Parar a recuperação quando pagar

Opção A — Webhook (recomendado)

Cadastre payment.paid e payment_link.paid. Ao receber o evento, marque transactionId ou externalReference como pago no seu sistema e não envie mais mensagens.
curl -X POST https://api.goatpay.com.br/v1/webhooks/create \
  -H "X-API-Key: gp_live_SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.suaempresa.com/goatpay/webhook",
    "events": ["payment.paid", "payment.pix.expired", "payment_link.paid"]
  }'
EventoAção no recuperador
payment.paidRemover da fila / marcar como convertido
payment_link.paidMesmo, para checkout via link
payment.pix.expiredOferecer novo link ou encerrar sequência
Webhooks na prática

Opção B — Reconsultar o extrato

No próximo ciclo do job, itens pagos saem do filtro status=PENDING. Mais simples, porém com atraso de até um ciclo do cron.

5. PIX expirado — segunda chance

QR expirado fica com status=CANCELED. Busque com janela recente:
curl -G 'https://api.goatpay.com.br/v1/account/transactions' \
  -H 'X-API-Key: gp_live_SUA_CHAVE' \
  --data-urlencode 'status=CANCELED' \
  --data-urlencode 'type=entrada' \
  --data-urlencode 'method=PIX' \
  --data-urlencode 'dateFrom=2026-06-23T00:00:00.000Z'
Se payer ainda tiver contato, envie mensagem com um novo link de pagamento (criar link ou nova cobrança PIX) em vez do qrcodeUrl antigo.
Origem da cobrançaDados do cliente no extrato
Link de pagamento (checkout GoatPay)payer com nome, documento, e-mail e telefone do formulário
POST /payment-pix/create sem checkoutGeralmente sem payer até o PIX ser pago (só nome/doc do comprovante)
Para recuperação rica em contato, venda pelo link de pagamento ou garanta que o checkout colete e-mail/telefone antes de gerar a cobrança. Consulta pontual de sessão: GET /payment-links/sessions/get.

7. Boas práticas

Deduplicação

Guarde transactionId (campo id) ou externalReference com timestamp do último contato. Não envie a mesma sequência duas vezes.

Janela de recuperação

TentativaSugestão
30–60 min após createdAt
6–12 h (antes de expiresAt)
Após expiração, com novo link

LGPD e opt-out

Use os dados apenas para concluir a compra iniciada. Ofereça descadastro e não compartilhe contatos com terceiros sem base legal.

Subcontas

Se cada lojista tem subconta, filtre merchantSubaccountId no extrato para recuperar só as vendas daquele parceiro.

Erros frequentes

SituaçãoCausaSolução
payer ausenteCobrança sem checkout de linkVender via link ou coletar contato no seu site
403Chave sem permissãoAdicione account/transactions
Lista vaziaFiltro de data/status restritoAmplie dateFrom ou remova method
Contato duplicadoMesmo cliente, várias cobrançasAgrupe por payer.email ou payer.phone
Mais ajuda: Troubleshooting · Extrato — referência