Busca avançada no extrato

O extrato comum (GET /v1/accounts/{accountId}/statement) filtra por período, tipo de operação e ordem. Essas três coisas o liquidante sabe fazer, e por isso elas são baratas.

Perguntas como “quais recebimentos caíram nesta chave PIX”, “o que veio deste CNPJ” ou “quais lançamentos passaram de R$ 5.000” o liquidante não sabe responder. A GET /v1/accounts/{accountId}/statement/advanced responde — percorrendo o extrato do período e avaliando linha a linha.

Este endpoint é caro. Leia antes de integrar.

Cada chamada varre o extrato do período página a página, porque o liquidante não filtra por esses campos. Uma única busca pode custar dezenas de requisições ao parceiro e demorar bem mais que o extrato comum.

Ele existe para facilitar consulta pontual, investigação e conciliação manual. Não deve ser abusado e, em hipótese alguma, usado para consulta recorrente ou polling.

  • Para acompanhar recebimentos em tempo real, use webhooks (pix.in.completed). O evento chega sozinho, na hora, sem custo de varredura.
  • Para volume ou fechamento, use o extrato comum paginado ou a exportação CSV.
  • Prefira sempre o extrato comum quando os filtros nativos bastarem. Recorra a este endpoint só quando precisar de um campo que só ele filtra.

Uso recorrente é detectável e será tratado como abuso, do mesmo modo que o consumo abusivo de consultas DICT.

A chave PIX agora aparece no extrato comum

Antes de recorrer à busca avançada, note que toda linha do extrato passou a trazer a chave usada na transação, no campo pixKey — tanto aqui quanto no extrato comum:

{
"endToEndId": "E18236120202608081220s15f7488fc7",
"direction": "IN",
"operation": "PIX",
"amount": 1300,
"pixKey": "5bdc1526-20c1-4820-ae06-cf9d6ff5a21c",
"counterParty": { "name": "Manaire da Costa Miranda", "document": "40579906825" }
}

O sentido do campo segue a direção do lançamento:

DireçãoO que pixKey significa
IN (crédito)a chave desta conta que recebeu o dinheiro
OUT (débito)a chave de destino do pagamento

Não confunda com counterParty.pixKey, que descreve a contraparte. Num crédito o liquidante costuma preencher pixKey e deixar a da contraparte vazia.

Se o que você precisa é apenas saber em que chave cada recebimento caiu, o extrato comum já responde, e sai muito mais barato: pagine normalmente e leia o campo. O export CSV/PDF/XLSX (POST /v1/accounts/{accountId}/exports) também traz pixKey em cada linha. A busca avançada só é necessária quando você precisa filtrar por ele.

Filtros disponíveis

Todos são opcionais e combinam entre si por E (todas as condições precisam valer).

ParâmetroEfeito
directionIN (créditos) ou OUT (débitos)
operationPIX, TED, INTERNAL_TRANSFER, BOLETO, FEE
statusCOMPLETED, PROCESSING, FAILED, REFUNDED, REVERSED
pixKeychave exata, ignorando maiúsculas/minúsculas
counterpartyNameparte do nome da contraparte
counterpartyDocumentCPF/CNPJ da contraparte, com ou sem máscara
minAmount / maxAmountfaixa de valor, pelo valor absoluto
startDate / endDateperíodo, no máximo 31 dias
occurredAfter / occurredBeforerecorte por horário dentro do período, RFC 3339 com fuso (2026-09-20T17:00:00-03:00), inclusivo nos dois lados
orderasc (padrão, do mais antigo ao mais recente, com cursor) ou desc (do mais recente ao mais antigo, continuação por tempo — veja abaixo)

Duas observações que evitam surpresa:

operation é o filtro mais barato. É o único que o liquidante consegue aplicar do lado dele, então informá-lo faz a varredura já chegar reduzida. Quando souber o tipo, informe.

A busca por nome é tolerante. Ignora acento e caixa, e não exige ordem: cada termo separado por espaço precisa aparecer em algum lugar do nome, em qualquer ordem. costa miranda e miranda costa acham “Manaire da Costa Miranda”; jose acha “José”.

Paginação por cursor

Não existe “página 2”. A posição de um lançamento no resultado filtrado não tem relação fixa com a posição dele no extrato bruto, então pular para uma página arbitrária exigiria varrer o período desde o começo outra vez.

Cada chamada gasta um orçamento limitado — um número máximo de páginas do liquidante e um teto de tempo. Quando o orçamento acaba antes do fim do período, a resposta traz exhausted: false e um nextCursor:

# Primeira chamada
curl -G "https://tenant.api.corpx.com/v1/accounts/$ACCOUNT/statement/advanced" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Tenant-Id: $TENANT" \
-d startDate=2026-07-10 -d endDate=2026-08-08 \
-d operation=PIX -d direction=IN \
-d pixKey=5bdc1526-20c1-4820-ae06-cf9d6ff5a21c
# Continuação, quando exhausted=false
curl -G "https://tenant.api.corpx.com/v1/accounts/$ACCOUNT/statement/advanced" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Tenant-Id: $TENANT" \
-d startDate=2026-07-10 -d endDate=2026-08-08 \
-d operation=PIX -d direction=IN \
-d pixKey=5bdc1526-20c1-4820-ae06-cf9d6ff5a21c \
-d cursor=MTA6NDI6MzE0MTU5

A resposta:

{
"accountId": "acc_...",
"startDate": "2026-07-10",
"endDate": "2026-08-08",
"items": [ /* linhas do extrato, mesmo formato do extrato comum */ ],
"size": 12,
"order": "asc",
"exhausted": false,
"nextCursor": "MTA6NDI6MzE0MTU5",
"partialReason": "scan_budget",
"scan": { "pagesRead": 10, "itemsScanned": 1000, "maxPages": 10 }
}

Repita passando cursor enquanto exhausted for false. Quando vier true, o período foi varrido até o fim e você tem tudo que casa com o filtro.

Por padrão, os resultados vêm do mais antigo para o mais recente

Sem order, a varredura é crescente e a resposta devolve order: "asc" para deixar isso explícito.

Isso é o que faz a retomada por cursor ser exata, não uma preferência de apresentação. O cursor é uma posição dentro do extrato do liquidante. Em ordem decrescente, um lançamento que chega no meio da varredura entra no topo e empurra todas as posições seguintes uma casa adiante — a chamada de continuação passaria a apontar para um item já entregue, e você receberia linha repetida. Em ordem crescente, o que chega entra no fim, e nada do que já foi varrido se move.

Como o período default é o dia corrente, a janela quase sempre inclui “agora” — ou seja, esse é o caso comum, não a exceção.

Quero só as mais recentes

Conta com milhares de lançamentos no dia e você precisa do fim do período, não do começo. Dois caminhos, do mais barato ao mais completo:

1. Se os filtros do extrato comum bastam, não use este endpoint. GET /v1/accounts/{accountId}/statement já devolve do mais recente para o mais antigo por padrão (order=desc) e aceita size até 500: a primeira página é o final do dia, a um custo de uma chamada.

2. Se precisa dos filtros avançados (chave PIX, contraparte, valor), use order=desc, de preferência com occurredAfter marcando a partir de quando você quer:

# Tudo que caiu nesta chave desde as 17h de hoje, do mais recente ao mais antigo
curl -G "https://tenant.api.corpx.com/v1/accounts/$ACCOUNT/statement/advanced" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Tenant-Id: $TENANT" \
-d order=desc \
-d occurredAfter=2026-09-20T17:00:00-03:00 \
-d direction=IN -d pixKey=5bdc1526-20c1-4820-ae06-cf9d6ff5a21c

A varredura começa pelo lançamento mais recente e para ao cruzar as 17h: exhausted: true, sem ler a manhã inteira. É isso que torna o modo barato — occurredAfter em desc é uma fronteira, não só um filtro.

Em desc não existe cursor (mandar um devolve 400 invalid_cursor), pelo motivo explicado acima: a posição se move quando entra lançamento novo. A continuação é por tempo. Quando exhausted vier false, a resposta traz nextOccurredBefore, o instante do último lançamento examinado; repita a chamada passando esse valor em occurredBefore:

{
"items": [ /* 50 lançamentos, do mais recente ao mais antigo */ ],
"size": 50,
"order": "desc",
"exhausted": false,
"partialReason": "page_full",
"nextOccurredBefore": "2026-09-20T17:42:10-03:00",
"scan": { "pagesRead": 2, "itemsScanned": 137, "maxPages": 10 }
}

Uma fronteira de tempo não se move quando chega lançamento novo no topo — por isso ela é segura onde o cursor não é. O preço é pequeno e previsível: como o limite é inclusivo, lançamentos que dividem o mesmo segundo com a fronteira podem voltar na chamada seguinte. Dedupe pelo id da linha. Exclusivo seria pior: pularia esses lançamentos em silêncio, e buraco você não detecta.

O outro custo é de varredura: cada continuação em desc relê do mais recente até a fronteira antes de avançar, porque o liquidante só pagina por posição. Para pegar o fim do dia isso é uma ou duas páginas e não importa; para varrer o dia inteiro de trás para a frente, importa — nesse caso use asc com cursor, que retoma exatamente de onde parou.

O que occurredAfter / occurredBefore fazem — e o que não fazem

Os dois recortam por horário dentro do período (startDate/endDate continuam valendo) e são inclusivos. Exigem fuso explícito (-03:00 ou Z): sem ele não há como saber se “18:00” é Brasília ou UTC, e um erro de três horas aqui passa despercebido até faltar dinheiro na conciliação.

encurtam a varredura quando são a fronteira na direção da varredura: occurredAfter em desc e occurredBefore em asc param a leitura ao serem cruzados. No sentido contrário são apenas filtro — o liquidante só aceita data, então as páginas anteriores ao horário são lidas do mesmo jeito. occurredAfter em asc, por exemplo, devolve menos linhas mas custa as mesmas páginas.

Resposta vazia com cursor não é resposta final

Uma chamada pode devolver zero itens e um cursor. Significa que o orçamento foi gasto em linhas que não casaram — não que não há o que achar. Continue pelo cursor.

O campo scan mostra o que a chamada custou. Use-o para dimensionar: uma busca que precisa de muitas continuações é sinal de que o período está largo demais ou de que o filtro deveria incluir operation.

O cursor pertence à busca

O cursor carrega a impressão digital dos filtros. Se você mudar qualquer um deles e reaproveitar o cursor, a API responde 400 invalid_cursor — recomece sem cursor.

Isso é proteção, não capricho: um cursor aplicado a outro filtro apontaria para uma posição sem relação com a nova busca, e o resultado viria silenciosamente errado.

Erros

CódigoQuando
date_range_too_wideperíodo acima de 31 dias
invalid_date_rangedatas malformadas ou fim antes do início
invalid_filtervalor fora do domínio (direction, operation, order), valor monetário inválido, instante sem fuso ou occurredAfter maior que occurredBefore
invalid_cursorcursor malformado, de outra combinação de filtros, ou enviado com order=desc
partner_rate_limitedo liquidante limitou nosso tráfego. Se a varredura já tinha coletado algo, devolvemos o parcial com cursor em vez de erro

No painel

A mesma busca está no backoffice, em Advanced search, com os filtros em formulário e o preset “recebimentos por chave” já montado. A tela mostra quantas linhas foram examinadas e marca o resultado como parcial enquanto a varredura não termina.