Pular para o conteúdo

API v1 · Guia

SDK e exemplos

Exemplos prontos em curl, Python, Node.js e n8n para criar contatos e negócios, e o SDK TypeScript.

Arquivos completos para copiar e rodar. Todos leem o token da variável de ambiente RUMO_TOKEN (crie em Configurações → API e integrações) e falam com o endereço de produção.

Exemplos prontos

  • curl

    Cria um contato, abre um negócio, move de etapa e percorre a lista página por página.

    exemplos.sh
  • Python (requests)

    O mesmo fluxo com requests, repetindo em 429 e 5xx sem duplicar (Idempotency-Key).

    exemplo.py
  • Node.js com o SDK

    O mesmo fluxo com o SDK TypeScript: tipos, paginação e erros prontos.

    exemplo.ts
  • Fluxo do n8n

    Recebe o webhook contact.created, confere a Rumo-Signature e cria um negócio. Importe no n8n.

    rumo-crm-contato-vira-negocio.json

SDK TypeScript

Prévia. O pacote @rumocrm/api ainda não está publicado no npm. Até lá, os exemplos em curl, Python e n8n funcionam sem ele.

  • Sem dependências: usa o fetch nativo (Node.js 20.3 ou mais novo e navegador).
  • Tipos de entrada e saída gerados da especificação OpenAPI.
  • listAll() percorre todas as páginas; erros chegam como RumoApiError com code e requestId.
  • Repete sozinho em 429 e 5xx, sempre com a mesma Idempotency-Key: a nova tentativa nunca duplica um contato, negócio ou mensagem.
  • webhookEndpoints.create() cadastra o endereço dos webhooks e verifyWebhookSignature() confere a Rumo-Signature, com o corpo de cada evento tipado.
TypeScript
// Cadastra um lead, abre um negócio no funil padrão, avança uma etapa e lista os negócios abertos.
// Rode com: RUMO_TOKEN=teha_pat_... npx tsx exemplo.ts   (Node 20.3+)
import { RateLimitError, RumoApiError, RumoCRM } from "@rumocrm/api";

const token = process.env.RUMO_TOKEN;
if (!token) throw new Error("Defina RUMO_TOKEN com um token criado em Configurações → API e integrações.");
const rumo = new RumoCRM({ token }); // endereço padrão: https://rumocrm.com/api/v1

async function main() {
  // Upsert: o mesmo telefone devolve o mesmo contato, nunca duplica.
  const contato = await rumo.contacts.upsert({ name: "Maria Souza", phone: "(15) 99807-3400", tags: ["site"] });

  const { data: funis } = await rumo.pipelines.list();
  const funil = funis.find((f) => f.isDefault) ?? funis[0];
  const { data: etapas } = await rumo.pipelines.listStages(funil.id);

  // valueCents: dinheiro em centavos (R$ 1.500,00).
  const negocio = await rumo.deals.create({
    title: `Proposta - ${contato.name}`,
    pipelineId: funil.id,
    contactId: contato.id,
    valueCents: 150000,
  });

  const segundaEtapa = etapas.filter((etapa) => etapa.type === "open")[1];
  if (segundaEtapa) await rumo.deals.move(negocio.id, { stageId: segundaEtapa.id });

  // Percorre todas as páginas sozinho (nextCursor/hasMore).
  for await (const aberto of rumo.deals.listAll({ pipelineId: funil.id, status: "open" })) {
    console.log(aberto.title, aberto.valueCents === null ? "sem valor" : aberto.valueCents / 100);
  }
}

main().catch((erro: unknown) => {
  if (erro instanceof RateLimitError) console.error(`Limite atingido; tente em ${erro.retryAfter ?? "?"} s`);
  else if (erro instanceof RumoApiError) console.error(erro.status, erro.code, erro.message, erro.requestId);
  else console.error(erro);
  process.exitCode = 1;
});
PróximoChangelog