API reference
Complete apicvm API documentation
Everything you need to integrate with Brazilian CVM filings: endpoints, query filters, response fields, error codes, and async text extraction callbacks.
Overview
All business routes use the prefix /v1. The base URL in production is
https://apicvm.dev. Authenticate with an API key on every business route
except GET /v1/health-check.
Public JSON fields use camelCase (for example
dateRef, idCompany). Internal fields such as
url, status, createdAt,
updatedAt, and allPagesDone are not returned in API
responses.
List and filter public companies.
Resolve a single company by ticker, CNPJ, or name.
List and filter CVM filings (DFP, ITR, FRE, etc.).
Queue async page-level markdown extraction.
Authentication
Send your API key on every business route. Prefer Bearer auth. Access is currently provisioned manually — there is no public self-serve signup on this site.
Authorization: Bearer apicvm_...
# or
X-API-Key: apicvm_...
| Header | Required | Description |
|---|---|---|
Authorization |
Yes (business routes) | Bearer apicvm_... — preferred method. |
X-API-Key |
Alternative | Same key value without the Bearer prefix. |
Content-Type |
POST only | application/json for text extraction requests. |
Errors
All errors follow a consistent envelope:
{
"error": {
"code": "DOCUMENT_NOT_FOUND",
"message": "Documento não encontrado",
"details": {}
}
}
| Status | Code | When |
|---|---|---|
| 401 | UNAUTHORIZED |
Missing or invalid API key. |
| 404 | COMPANY_NOT_FOUND |
No company matches the 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 request body. |
| 429 | RATE_LIMIT_EXCEEDED |
Per-key rate limit exceeded. |
| 500 | INTERNAL_SERVER_ERROR |
Unexpected server error. |
Ambiguous company resolve returns 409 with a
candidates array instead of picking a match silently.
Pagination and sorting
List endpoints accept these shared query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
integer | 1 | Page number (1-based). |
perPage |
integer | 10 | Items per page. Maximum 50. |
field |
string | varies | Sort field. Must be a valid model attribute. |
order |
asc | desc |
varies | Sort direction. |
Paginated responses use Lucid-style meta + data:
{
"meta": {
"total": 120,
"perPage": 10,
"currentPage": 1,
"lastPage": 12,
"firstPage": 1,
"firstPageUrl": "...",
"lastPageUrl": "...",
"nextPageUrl": "...",
"previousPageUrl": null
},
"data": [ ... ]
}
Default sort for companies: name asc. Default sort for documents:
year desc, then dateRef desc, then name asc.
Rate limits
When authentication and rate limiting are enabled, limits apply per API key via Redis. Default window: 60 seconds. Default max requests: 60 per window.
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests allowed in the current window. |
X-RateLimit-Remaining |
Requests remaining in the current window. |
X-RateLimit-Reset |
Unix timestamp when the window resets. |
Health check
Public endpoint. No authentication required.
Response 200
{ "status": "ok" }
List companies
Returns a paginated list of Brazilian public companies with tickers.
Query parameters
| Parameter | Type | Description |
|---|---|---|
id |
integer | Filter by company ID. |
search |
string | Search by name, sector, or CNPJ (partial match). |
ticker |
string | Filter by ticker (case-insensitive). |
cnpj |
string | Filter by CNPJ. Accepts formatted or digits-only. |
name |
string | Partial match on company name. |
status |
ACTIVE | INACTIVE |
Filter by company status. |
page, perPage, field, order |
— | Pagination and sorting (see above). |
Response fields (data[])
| Field | Type | Description |
|---|---|---|
id |
integer | Company ID. |
name |
string | Legal company name. |
cnpj |
string | CNPJ (digits only). |
sector |
string | null | Industry sector when available. |
tickers[] |
array | List of tickers. Each item has id, idCompany, ticker, tickerClass. |
Example
GET /v1/companies?search=Petrobras&perPage=5
{
"meta": { "total": 1, "perPage": 5, "currentPage": 1, "lastPage": 1 },
"data": [
{
"id": 42,
"name": "Petróleo Brasileiro S.A. - Petrobras",
"cnpj": "33000167000101",
"sector": "Petróleo, Gás e Biocombustíveis",
"tickers": [
{ "id": 1, "idCompany": 42, "ticker": "PETR4", "tickerClass": "ON" }
]
}
]
}
Resolve company
Find a single company by ticker, CNPJ, or name. Returns one match or an ambiguity error with candidates.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | Yes | Ticker, CNPJ, or company name. |
by |
auto | ticker | cnpj | name |
No | Resolution strategy. Default: auto. |
Resolution order (by=auto)
- Exact ticker match (case-insensitive).
- CNPJ match (formatted or digits-only).
- Exact name match (case-insensitive).
- Partial name match.
Response fields
Same shape as a single company object from the list endpoint.
Example — success
GET /v1/companies/resolve?query=PETR4&by=ticker
{
"id": 42,
"name": "Petróleo Brasileiro S.A. - Petrobras",
"cnpj": "33000167000101",
"sector": "Petróleo, Gás e Biocombustíveis",
"tickers": [
{ "id": 1, "idCompany": 42, "ticker": "PETR4", "tickerClass": "ON" }
]
}
Example — ambiguous (409)
{
"error": {
"code": "AMBIGUOUS_RESULT",
"message": "Mais de uma empresa corresponde à busca",
"details": {
"candidates": [
{ "id": 10, "name": "...", "cnpj": "...", "sector": null, "tickers": ["ABC3"] },
{ "id": 11, "name": "...", "cnpj": "...", "sector": null, "tickers": ["ABC4"] }
]
}
}
}
List documents
Returns a paginated list of CVM filings. Filter by company, ticker, type, year, and
more. Each item includes nested company with tickers.
Query parameters
| Parameter | Type | Description |
|---|---|---|
id |
UUID string | Filter by document ID. |
companyId |
integer | Filter by company ID. |
ticker |
string | Filter by company ticker (case-insensitive). |
cnpj |
string | Filter by company CNPJ. Accepts formatted or digits-only. |
companyName |
string | Partial match on company name. |
search |
string | Search document name or type (partial match). |
year |
integer | Filter by filing year (2000–2100). |
type |
string | Filter by single document type (e.g. DFP, ITR, FRE). |
types |
string | Comma-separated list of types (e.g. DFP,ITR). |
dateRef |
string | Filter by reference date (YYYY-MM-DD). Use Sem data for documents without a date. |
name |
string | Partial match on document name. |
page, perPage, field, order |
— | Pagination and sorting (see above). |
Response fields (data[])
| Field | Type | Description |
|---|---|---|
id |
UUID string | Document ID. |
type |
string | Document type (DFP, ITR, FRE, etc.). |
dateRef |
string | null | Reference date (YYYY-MM-DD). |
idCompany |
integer | Company ID. |
year |
integer | Filing year. |
name |
string | null | Document display name. |
hash |
string | null | Content hash when available. |
company |
object | Nested company with id, name, cnpj, sector, tickers[]. |
Example
GET /v1/documents?ticker=PETR4&type=DFP&year=2024&perPage=20
Get document
Returns metadata for a single document, including nested company and tickers.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id |
UUID string | Document ID from a list or resolve flow. |
Example
GET /v1/documents/550e8400-e29b-41d4-a716-446655440000
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "DFP",
"dateRef": "2024-12-31",
"idCompany": 42,
"year": 2024,
"name": "DFP 2024",
"hash": null,
"company": {
"id": 42,
"name": "Petróleo Brasileiro S.A. - Petrobras",
"cnpj": "33000167000101",
"sector": "Petróleo, Gás e Biocombustíveis",
"tickers": [
{ "id": 1, "idCompany": 42, "ticker": "PETR4", "tickerClass": "ON" }
]
}
}
Download file
Streams the original CVM filing file from storage. Useful when you need the source PDF, not just metadata or extracted text.
Response headers
| Header | Description |
|---|---|
Content-Type |
application/pdf, text/plain, or application/octet-stream. |
Content-Length |
File size in bytes. |
Content-Disposition |
inline; filename="..." |
Cache-Control |
private, max-age=300 |
Example
curl -OJ -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/documents/550e8400-e29b-41d4-a716-446655440000/file"
Text extraction
Queue an async extraction job. Pages are delivered to your
callback_url as markdown as they complete. There is no job status
endpoint — progress arrives only via callbacks.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
callback_url |
string (URL) | Yes | HTTPS URL that receives page callbacks. Must include protocol. |
document.id |
UUID string | Yes | Document ID to extract. |
Example request
POST /v1/document-text-extractions
Content-Type: application/json
{
"callback_url": "https://you.example.com/callbacks/apicvm",
"document": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Response 202
{
"id": "job-uuid",
"status": "queued",
"document_id": "550e8400-e29b-41d4-a716-446655440000"
}
If the document was already fully extracted and cached, the worker reuses existing page text and sends callbacks from cache.
Examples
Recommended agent flow: resolve company → list documents → pick an explicit id → download file or enqueue extraction.
cURL
# Resolve a Brazilian company
curl -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/companies/resolve?query=PETR4&by=ticker"
# List 2024 DFP filings
curl -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/documents?ticker=PETR4&type=DFP&year=2024"
# Download original file
curl -OJ -H "Authorization: Bearer $APICVM_KEY" \
"$APICVM_URL/v1/documents/$DOCUMENT_ID/file"
# Queue text extraction
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
import requests
BASE_URL = os.environ["APICVM_URL"]
HEADERS = {"Authorization": f"Bearer {os.environ['APICVM_KEY']}"}
# Resolve company
company = requests.get(
f"{BASE_URL}/v1/companies/resolve",
params={"query": "PETR4", "by": "ticker"},
headers=HEADERS,
).json()
# List DFP filings for 2024
documents = requests.get(
f"{BASE_URL}/v1/documents",
params={"ticker": "PETR4", "type": "DFP", "year": 2024},
headers=HEADERS,
).json()
document_id = documents["data"][0]["id"]
# Download original PDF
pdf = requests.get(
f"{BASE_URL}/v1/documents/{document_id}/file",
headers=HEADERS,
)
pdf.raise_for_status()
# Queue text extraction
job = requests.post(
f"{BASE_URL}/v1/document-text-extractions",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"callback_url": "https://you.example.com/callbacks/apicvm",
"document": {"id": document_id},
},
)
job.raise_for_status()
print(job.json()) # {"id": "...", "status": "queued", "document_id": "..."}
TypeScript
const baseUrl = process.env.APICVM_URL!
const apiKey = process.env.APICVM_KEY!
async function apicvmGet(path: string) {
const response = await fetch(`${baseUrl}${path}`, {
headers: { Authorization: `Bearer ${apiKey}` },
})
if (!response.ok) throw new Error(await response.text())
return response.json()
}
const company = await apicvmGet('/v1/companies/resolve?query=PETR4&by=ticker')
const documents = await apicvmGet('/v1/documents?ticker=PETR4&type=DFP&year=2024')
const documentId = documents.data[0].id
const extraction = await fetch(`${baseUrl}/v1/document-text-extractions`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
callback_url: 'https://you.example.com/callbacks/apicvm',
document: { id: documentId },
}),
})
Extraction callbacks
After a successful POST /v1/document-text-extractions, the worker sends
one callback per page to your callback_url. Callbacks have retry logic
(up to 3 attempts). Your endpoint should be idempotent.
Page callback (success)
{
"status": "success",
"document_id": "550e8400-e29b-41d4-a716-446655440000",
"job_id": "job-uuid",
"page": {
"number": 1,
"markdown": "# Demonstrações Financeiras\n\n..."
},
"current_page": 1,
"total_pages": 120,
"is_last_page": false
}
Error callback
{
"status": "error",
"document_id": "550e8400-e29b-41d4-a716-446655440000",
"job_id": "job-uuid",
"error_message": "Description of the error"
}
| Field | Type | Description |
|---|---|---|
status |
success | error |
Callback outcome. |
document_id |
UUID string | Document being extracted. |
job_id |
string | Extraction job ID from the 202 response. |
page.number |
integer | 1-based page number. |
page.markdown |
string | Page content as markdown. |
current_page |
integer | Index of this callback (1-based). |
total_pages |
integer | Total pages in the document. |
is_last_page |
boolean | true on the final page callback. |
error_message |
string | Present when status is error. |
For AI agents
Download llms.txt for a plain-text summary of this API — endpoints,
filters, examples, and limitations — optimized for LLM and agent consumption without
parsing HTML.
llms.txt
Machine-readable API reference. Point your agent at
https://apicvm.dev/llms.txt or download the file locally.