Access Brazil CVM Filings with Node.js

Need a Node.js CVM filings API client? apicvm speaks HTTPS JSON. On Node 18+, use native fetch (undici), a Bearer token, and /v1/* — no SDK required. For typed clients, see the TypeScript guide; this page stays on the Node runtime path.

The problem

Backend jobs and agent runtimes often need Brazilian filings without:

  • Puppeteer against the CVM portal
  • One-off Python sidecars just to pull a PDF
  • Fragile CSV dumps that lack document UUIDs

A few fetch calls keep the pipeline inside your existing Node service.

Setup

export APICVM_URL='https://apicvm.dev'
export APICVM_KEY='apicvm_...'   # from /signup
// node --env-file=.env resolve.mjs  (Node 20+)
const BASE = process.env.APICVM_URL;
const H = { Authorization: `Bearer ${process.env.APICVM_KEY}` };

Resolve a ticker

const url = new URL("/v1/companies/resolve", BASE);
url.searchParams.set("query", "PETR4");
url.searchParams.set("by", "ticker");

const res = await fetch(url, { headers: H });
if (!res.ok) {
  throw new Error(`HTTP ${res.status}: ${await res.text()}`);
}
const company = await res.json();
console.log(company);

List DFP documents

const listUrl = new URL("/v1/documents", BASE);
listUrl.searchParams.set("ticker", "PETR4");
listUrl.searchParams.set("type", "DFP");
listUrl.searchParams.set("year", "2024");
listUrl.searchParams.set("perPage", "20");

const docs = await fetch(listUrl, { headers: H }).then((r) => r.json());
for (const row of docs.data) {
  console.log(row.id, row.name);
}

perPage max is 50. Paginate with page until meta.lastPage. See Paginate and filter.

Download a PDF

import { writeFile } from "node:fs/promises";

const docId = "..."; // UUID from list
const fileRes = await fetch(`${BASE}/v1/documents/${docId}/file`, {
  headers: H,
});
if (!fileRes.ok) throw new Error(`HTTP ${fileRes.status}`);
const buf = Buffer.from(await fileRes.arrayBuffer());
await writeFile("petr4-dfp.pdf", buf);

File download does not consume extraction credits.

Optional: start async text extraction

const extractRes = await fetch(`${BASE}/v1/document-text-extractions`, {
  method: "POST",
  headers: { ...H, "Content-Type": "application/json" },
  body: JSON.stringify({
    documentId: docId,
    callbackUrl: "https://example.com/hooks/apicvm",
  }),
});
// 202 Accepted — progress arrives on the callback, not a sync body

Extraction is async and needs an HTTPS callback in production. Student keys get 403 for extract. Details: Async CVM PDF extraction.

Errors and rate limits

Check res.status before json(). On 429, read X-RateLimit-Reset. Guide: Handle errors and rate limits.

Current limitations

  • No official npm package — bring your own fetch wrapper.
  • Extraction progress is callback-only (no job polling endpoint).
  • Corpus coverage depends on ingestion; always resolve before hard-coding CNPJ.

Next steps

Ready to integrate?

Get an API key and start querying Brazilian CVM filings programmatically.