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 async — POST /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.
perPagecaps at 50; large result sets need pagination withpage=.- curl downloads binary PDFs — parse JSON with jq, not plain
curloutput 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.