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 payer | Uso na recuperação |
|---|
name | Personalizar mensagem |
email | E-mail transacional |
phone | WhatsApp / SMS |
document | Identificar 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ão | Para quê |
|---|
account/transactions | Listar cobranças e ler payer |
webhooks/create | Opcional — 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
| Query | Recuperação de… |
|---|
status=PENDING | PIX/boleto ainda não pagos |
status=CANCELED + janela curta | QR PIX expirado (reenviar link) |
type=entrada | Só recebimentos (ignora saques) |
method=PIX / Boleto / Cartão | Canal específico |
externalReference=pedido-42 | Pedido pontual no seu sistema |
merchantSubaccountId=clx_sub | Extrato 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"]
}'
| Evento | Ação no recuperador |
|---|
payment.paid | Remover da fila / marcar como convertido |
payment_link.paid | Mesmo, para checkout via link |
payment.pix.expired | Oferecer novo link ou encerrar sequência |
Webhooks na prática
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.
6. Links de pagamento vs cobrança direta
| Origem da cobrança | Dados 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 checkout | Geralmente 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
| Tentativa | Sugestão |
|---|
| 1ª | 30–60 min após createdAt |
| 2ª | 6–12 h (antes de expiresAt) |
| 3ª | 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ção | Causa | Solução |
|---|
payer ausente | Cobrança sem checkout de link | Vender via link ou coletar contato no seu site |
| 403 | Chave sem permissão | Adicione account/transactions |
| Lista vazia | Filtro de data/status restrito | Amplie dateFrom ou remova method |
| Contato duplicado | Mesmo cliente, várias cobranças | Agrupe por payer.email ou payer.phone |
Mais ajuda: Troubleshooting · Extrato — referência