API v1 · Guia
Paginação e updatedSince
Percorra listas com cursor e sincronize só o que mudou com updatedSince, passo a passo.
Listas respondem { "data": [...], "nextCursor": "...", "hasMore": true }. Para a página
seguinte, repita o mesmo pedido com cursor=<nextCursor>. Quando hasMore for false,
nextCursor vem null e a lista acabou. A ordem é estável: um registro nunca aparece
duas vezes nem fica de fora entre páginas, mesmo com datas de criação iguais.
Para sincronizar só o que mudou, guarde a hora em que a sincronização começou e, na
próxima, envie updatedSince com essa hora.
Percorrer uma lista inteira
Peça páginas de 100 itens (o máximo) e siga o nextCursor até hasMore vir false. Envie o cursor exatamente como veio.
const BASE = "https://rumocrm.com/api/v1";
const CABECALHOS = { Authorization: `Bearer ${process.env.RUMO_TOKEN}` };
// Devolve todos os itens de uma lista, página por página.
async function* todos(caminho, filtros = {}) {
let cursor = null;
do {
const url = new URL(BASE + caminho);
for (const [chave, valor] of Object.entries({ ...filtros, limit: 100 })) url.searchParams.set(chave, valor);
if (cursor) url.searchParams.set("cursor", cursor);
const resposta = await fetch(url, { headers: CABECALHOS });
if (!resposta.ok) throw new Error(`${resposta.status}: ${await resposta.text()}`);
const pagina = await resposta.json();
yield* pagina.data;
cursor = pagina.hasMore ? pagina.nextCursor : null;
} while (cursor);
}Sincronização incremental, passo a passo
- Primeira carga. Anote a hora de início, percorra a lista inteira sem
updatedSincee grave cada registro no seu sistema peloid(cria se não existe, atualiza se existe). - Guarde a marca. Terminou sem erro? Salve a hora de início como a marca da última sincronização. Se falhar no meio, não salve: a próxima rodada repete do mesmo ponto e nada se perde.
- Próximas rodadas. Anote a nova hora de início e peça só o que mudou desde a marca, com uma folga
de um minuto para trás:
updatedSince=<marca − 1 min>. Percorra todas as páginas gravando peloid. - Avance a marca. Ao terminar, salve a nova hora de início.
Por que funciona: updatedSince é inclusivo (igual ou depois) e a folga cobre a diferença entre o
relógio do seu servidor e o nosso. Um registro alterado durante a rodada volta na rodada seguinte e um
criado durante a rodada também; como você grava pelo id, repetir não duplica nada.
Não troque os filtros entre uma página e outra: o cursor vale para a lista que o gerou e, alterado,
responde 400 invalid_cursor. Para reagir na hora em vez de perguntar de tempos em tempos, use os
webhooks.
const FOLGA_MS = 60_000;
async function sincronizarContatos() {
const marca = await lerMarca(); // null na primeira carga
const inicio = new Date();
const filtros = marca ? { updatedSince: new Date(marca.getTime() - FOLGA_MS).toISOString() } : {};
for await (const contato of todos("/contacts", filtros)) {
await gravarPeloId(contato); // upsert no seu banco
}
await salvarMarca(inicio); // só depois de terminar sem erro
}Listas que aceitam updatedSince
- GETListar contatos
/contacts - GETListar empresas
/companies - GETListar negócios
/deals - GETListar canais
/channels - GETListar conversas
/conversations - GETListar mensagens da conversa
/conversations/{id}/messages