# apicvm — Brazil CVM Filings API > Programmatic access to Brazilian public company filings (DFP, ITR, FRE, and other CVM documents) for developers, scripts, and AI agents. Base URL: https://apicvm.dev API prefix: /v1 Documentation: https://apicvm.dev/docs ## Authentication All business routes require an API key. Health check is public. Preferred: Authorization: Bearer apicvm_... Alternative: X-API-Key: apicvm_... Access is provisioned manually. No public self-serve signup or pricing. ## Rate limits Per API key when enabled. Response headers: X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset Exceeding the limit returns 429 with code RATE_LIMIT_EXCEEDED. ## Error format { "error": { "code": "DOCUMENT_NOT_FOUND", "message": "Documento não encontrado", "details": {} } } Common codes: 401 UNAUTHORIZED — missing or invalid API key 404 COMPANY_NOT_FOUND — no company matches resolve query 404 DOCUMENT_NOT_FOUND — document or file not found 409 AMBIGUOUS_RESULT — resolve found multiple companies (see details.candidates) 422 VALIDATION_FAILED — invalid query params or body 422 INVALID_CALLBACK_URL — callback_url blocked (SSRF, private IP, HTTP in prod; see details.reason) 429 RATE_LIMIT_EXCEEDED — rate limit exceeded 500 INTERNAL_SERVER_ERROR — server error ## Pagination List endpoints accept: page, perPage (max 50, default 10), field, order (asc|desc). Response shape: { "meta": { "total", "perPage", "currentPage", "lastPage", ... }, "data": [...] } Default sort: companies — name asc documents — year desc, dateRef desc, name asc Public JSON fields use camelCase. Internal fields (url, status, createdAt, updatedAt, allPagesDone, isPrimary) are not returned. ## Endpoints ### GET /v1/health-check Public. No auth required. Response 200: { "status": "ok" } ### GET /v1/companies List Brazilian public companies (paginated). Query filters: id (integer) — company ID search (string) — name, sector, or CNPJ (partial) ticker (string) — case-insensitive ticker match cnpj (string) — formatted or digits-only name (string) — partial name match status (ACTIVE|INACTIVE) page, perPage, field, order Response data[] fields: id, name, cnpj, sector, tickers[] tickers[]: id, idCompany, ticker, tickerClass Example: GET /v1/companies?search=Petrobras&perPage=5 ### GET /v1/companies/resolve Resolve a single company by ticker, CNPJ, or name. Query params: query (required) — ticker, CNPJ, or company name by (optional) — auto|ticker|cnpj|name (default: auto) Resolution order (by=auto): 1. ticker (case-insensitive) 2. CNPJ (formatted or digits) 3. exact name (case-insensitive) 4. partial name Returns single company object on success. Returns 409 AMBIGUOUS_RESULT with candidates[] when multiple matches. Returns 404 COMPANY_NOT_FOUND when no match. Example: GET /v1/companies/resolve?query=PETR4&by=ticker ### GET /v1/documents List CVM filings (paginated). Each item includes nested company with tickers. Query filters: id (UUID) — document ID companyId (integer) ticker (string) — company ticker, case-insensitive cnpj (string) — company CNPJ, formatted or digits companyName (string) — partial company name search (string) — document name or type year (integer) — 2000–2100 type (string) — single type e.g. DFP, ITR, FRE types (string) — comma-separated e.g. DFP,ITR dateRef (string) — YYYY-MM-DD, or "Sem data" for null dates name (string) — partial document name page, perPage, field, order Response data[] fields: id, type, dateRef, idCompany, year, name, hash, company company: id, name, cnpj, sector, tickers[] Example: GET /v1/documents?ticker=PETR4&type=DFP&year=2024&perPage=20 ### GET /v1/documents/:id Document metadata with nested company and tickers. Path: id (UUID) Example: GET /v1/documents/550e8400-e29b-41d4-a716-446655440000 ### GET /v1/documents/:id/file Stream original filing file (PDF or other). Response headers: Content-Type: application/pdf | text/plain | application/octet-stream Content-Length, Content-Disposition (inline), Cache-Control: private, max-age=300 Example: curl -OJ -H "Authorization: Bearer $APICVM_KEY" \ "$APICVM_URL/v1/documents/$DOCUMENT_ID/file" ### POST /v1/document-text-extractions Queue async page-level markdown extraction. Request body: { "callback_url": "https://you.example.com/callbacks/apicvm", "document": { "id": "uuid" } } Response 202: { "id": "job-id", "status": "queued", "document_id": "uuid" } No job status endpoint. Progress arrives via callbacks only. Cached documents reuse existing page text. ## Recommended agent flow 1. Resolve company: GET /v1/companies/resolve?query=PETR4&by=ticker 2. List documents: GET /v1/documents?ticker=PETR4&type=DFP&year=2024 3. Pick explicit document id from results 4. Download file: GET /v1/documents/:id/file OR queue extraction: POST /v1/document-text-extractions The API does not auto-select a document when filters are ambiguous. ## Extraction callbacks Worker sends one callback per page to callback_url. Retries up to 3 times. Your endpoint must be idempotent. Page success: { "status": "success", "document_id": "uuid", "job_id": "job-id", "page": { "number": 1, "markdown": "# ..." }, "current_page": 1, "total_pages": 120, "is_last_page": false } Error: { "status": "error", "document_id": "uuid", "job_id": "job-id", "error_message": "Description" } ## CVM document types DFP — Demonstrações Financeiras Padronizadas (annual standardized financial statements) ITR — Informações Trimestrais (quarterly financial information) FRE — Formulário de Referência (reference form: profile, risks, governance) ## Limitations (current MVP) - No public self-serve signup, billing, or pricing portal - No HTTP job status endpoint beyond initial 202 response - Callback URL is client responsibility; handle retries idempotently - Extraction progress only via callbacks - Access provisioned with API keys ## Examples curl: export APICVM_KEY='apicvm_...' export APICVM_URL='https://apicvm.dev' curl -H "Authorization: Bearer $APICVM_KEY" \ "$APICVM_URL/v1/companies/resolve?query=PETR4&by=ticker" curl -H "Authorization: Bearer $APICVM_KEY" \ "$APICVM_URL/v1/documents?ticker=PETR4&type=DFP&year=2024" curl -OJ -H "Authorization: Bearer $APICVM_KEY" \ "$APICVM_URL/v1/documents/$DOCUMENT_ID/file" curl -X POST -H "Authorization: Bearer $APICVM_KEY" \ -H "Content-Type: application/json" \ -d '{"callback_url":"https://you.example.com/cb","document":{"id":"'"$DOCUMENT_ID"'"}}' \ "$APICVM_URL/v1/document-text-extractions" Python: import os, requests BASE = os.environ["APICVM_URL"] H = {"Authorization": f"Bearer {os.environ['APICVM_KEY']}"} docs = requests.get(f"{BASE}/v1/documents", params={"ticker":"PETR4","type":"DFP","year":2024}, headers=H).json() doc_id = docs["data"][0]["id"] requests.post(f"{BASE}/v1/document-text-extractions", headers={**H,"Content-Type":"application/json"}, json={"callback_url":"https://you.example.com/cb","document":{"id":doc_id}})