Access Brazil CVM Filings with curl

Shell scripts and quick evaluations often start with curl — no SDK install, no virtualenv. If you need a CVM filings API curl workflow for Brazilian public companies, apicvm exposes stable /v1 routes for resolve, list, metadata, and file download.

This guide gives copy-paste commands for PETR4 and DFP 2024, plus error handling and a keyless demo alternative for VALE3.

Prerequisites

Set environment variables once per shell session:

export APICVM_URL='https://apicvm.dev'
export APICVM_KEY='apicvm_...'   # from /signup

Business routes require authentication when auth is enabled (production default). Pass the key on every call below except health-check.

Authentication headers

Two equivalent options:

# Preferred
-H "Authorization: Bearer $APICVM_KEY"

# Alternative
-H "X-API-Key: $APICVM_KEY"

Do not commit keys to git or paste them into public gist URLs. Use env vars or a secret manager in CI.

For header details and 401 debugging, see CVM API authentication.

Step 1: Health check (no auth)

Verify connectivity before spending rate limit quota:

curl "$APICVM_URL/v1/health-check"

Expected response:

{ "status": "ok" }

This route is public — no API key required.

Step 2: Resolve PETR4

Map ticker to company metadata:

curl -s -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/companies/resolve?query=PETR4&by=ticker" | jq .

Response includes id, name, cnpj, sector, and tickers[].

Ambiguity: multiple matches return 409 AMBIGUOUS_RESULT with details.candidates[]. Narrow with by=cnpj or an exact name — the API never silently picks one.

Step 3: List DFP 2024 filings

Filter documents by ticker, type, and year:

curl -s -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/documents?ticker=PETR4&type=DFP&year=2024&perPage=20" | jq .

Each data[] item includes:

Field Use
id UUID for download or extraction
type DFP, ITR, FRE, …
year Filing year
name Original file name as filed
dateRef Reference date
company Nested company with tickers

Pick a document.id explicitly. The API does not auto-select when filters match multiple PDFs.

perPage max is 50. Default sort: year desc, dateRef desc, name asc.

Extract an ID with jq:

DOC_ID=$(curl -s -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/documents?ticker=PETR4&type=DFP&year=2024&perPage=1" \
  | jq -r '.data[0].id')
echo "$DOC_ID"

Step 4: Document metadata

Inspect one document before download:

curl -s -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/documents/$DOC_ID" | jq .

Use this when you already have a UUID from a database or prior script run and need to confirm type, year, and name.

Step 5: Download the PDF

Stream the original file from storage:

curl -OJ -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/documents/$DOC_ID/file"

-OJ writes the file using the server-provided filename from Content-Disposition. Response headers include Content-Type (usually application/pdf) and Content-Length.

Alternative — explicit output path:

curl -o petr4-dfp-2024.pdf -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/documents/$DOC_ID/file"

Download does not consume extraction credits.

Rate limit headers

Successful authenticated responses include:

Header Meaning
X-RateLimit-Limit Max requests in the window
X-RateLimit-Remaining Requests left
X-RateLimit-Reset Window reset (Unix timestamp)

Inspect them:

curl -s -D - -o /dev/null -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/companies/resolve?query=PETR4&by=ticker" \
  | grep -i x-ratelimit

Excess returns 429 RATE_LIMIT_EXCEEDED. See errors and rate limits.

Error handling

Common failures and what to check:

Status Code Fix
401 UNAUTHORIZED Missing or invalid key
404 COMPANY_NOT_FOUND Ticker typo or company not in corpus
404 DOCUMENT_NOT_FOUND Bad UUID or file missing from bucket
409 AMBIGUOUS_RESULT Narrow resolve query
429 RATE_LIMIT_EXCEEDED Back off until X-RateLimit-Reset

Example error body:

{
  "error": {
    "code": "DOCUMENT_NOT_FOUND",
    "message": "Documento não encontrado",
    "details": {}
  }
}

Optional: document prefix catalog

List known section prefixes for a filing type (useful for FRE bundles):

curl -s -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/document-prefixes?type=FRE" | jq .

Filter list calls with name= to target a section — see filter CVM filings by section name.

Demo alternative (no API key)

To try the API before signup, use public demo routes — VALE3 only:

curl "$APICVM_URL/v1/demo/companies/resolve?query=VALE3&by=ticker"
curl "$APICVM_URL/v1/demo/documents?ticker=VALE3&type=FRE&year=2025&name=DescricaoFatoresRisco&perPage=5"

Demo is rate-limited per IP (30/min, 200/day). Download and markdown are limited to FRE 2025 risk factors. Full walkthrough: Try the apicvm demo API with VALE3.

What curl does not cover here

Text extraction is asyncPOST /v1/document-text-extractions returns 202 and delivers pages via callback. There is no synchronous "print all markdown" curl one-liner for authenticated routes. See extract text from CVM PDFs for AI agents.

Current limitations

  • Corpus reflects Hold ingestion — not every B3 company or period may appear in list results.
  • perPage caps at 50; large result sets need pagination with page=.
  • curl downloads binary PDFs — parse JSON with jq, not plain curl output alone.
  • No built-in retry or backoff — wrap scripts for production use.

Next steps

Ready to integrate?

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