Paginação
/v1/buscar pagina por offset. Oportunidades e despesas federais paginam por cursor, preso à publicação consultada. Cada página é uma chamada e conta na cota.
Offset: empresas
/v1/buscar recebe limit (1 a 100, padrão 20) e offset (padrão 0). has_more indica se há ao menos mais um resultado.
bash
curl -G https://api.fonteza.com.br/v1/buscar \
-H "X-Api-Key: $FONTEZA_KEY" \
--data-urlencode "q=transportadora" \
--data-urlencode "uf=SP" \
--data-urlencode "limit=100" \
--data-urlencode "offset=100"totalvemnull. Para o total exato, envieincluir_total=true; a contagem é mais lenta em buscas grandes.- Páginas fundas são caras. Refine por UF, município, CNAE ou porte em vez de percorrer milhares de resultados.
Cursor: oportunidades e despesas
/v1/oportunidades e /v1/empresas/{cnpj}/despesas-federais recebem limit (1 a 100, padrão 20) e cursor. Enquanto has_more for true, envie o next_cursor com os mesmos filtros.
- O cursor é opaco: não monte nem altere.
- Trocar filtros mantendo o cursor responde
422. - O cursor fica preso à publicação (
meta.geracao). Se uma nova carga entrar no ar no meio da paginação, a resposta é409 geracao_oportunidades_expiradaou409 geracao_despesas_expirada: recomece sem cursor e descarte o que veio da publicação anterior.
import os
import requests
URL = "https://api.fonteza.com.br/v1/oportunidades"
HEADERS = {"X-Api-Key": os.environ["FONTEZA_KEY"]}
FILTROS = {"q": "mobiliário", "status": "aberta", "limit": 100}
def todas_as_paginas():
params = dict(FILTROS)
while True:
resposta = requests.get(URL, headers=HEADERS, params=params, timeout=30)
if resposta.status_code == 409:
params = dict(FILTROS) # nova publicação: recomece do início
continue
resposta.raise_for_status()
pagina = resposta.json()
yield from pagina["items"]
if not pagina["has_more"]:
return
params = {**FILTROS, "cursor": pagina["next_cursor"]}const FILTROS = { q: "mobiliário", status: "aberta", limit: "100" };
async function* todasAsPaginas() {
let params = { ...FILTROS };
while (true) {
const url = new URL("https://api.fonteza.com.br/v1/oportunidades");
url.search = new URLSearchParams(params);
const resposta = await fetch(url, { headers: { "X-Api-Key": process.env.FONTEZA_KEY } });
if (resposta.status === 409) {
params = { ...FILTROS }; // nova publicação: recomece do início
continue;
}
if (!resposta.ok) throw new Error(`${resposta.status}: ${await resposta.text()}`);
const pagina = await resposta.json();
yield* pagina.items;
if (!pagina.has_more) return;
params = { ...FILTROS, cursor: pagina.next_cursor };
}
}