Load Brazil CVM Filings in R

Analysts who live in R still need primary filings — not only scraped tables. This guide shows an R CVM filings API workflow with httr2: resolve a ticker, list documents, download PDFs.

The problem

R packages that parse CVM ZIP/CSV dumps help for accounting panels. They do not give you:

  • Ticker-first document lists with stable IDs
  • Section-level FRE PDFs filtered by name
  • A single auth pattern for production jobs

Install and auth

install.packages("httr2")
library(httr2)

base <- Sys.getenv("APICVM_URL", "https://apicvm.dev")
key  <- Sys.getenv("APICVM_KEY")  # from /signup

apicvm_get <- function(path, ...) {
  req <- request(paste0(base, path)) |>
    req_headers(Authorization = paste("Bearer", key)) |>
    req_url_query(...)
  resp <- req_perform(req)
  resp_body_json(resp)
}

Resolve and list DFP 2024 for VALE3

company <- apicvm_get("/v1/companies/resolve", query = "VALE3", by = "ticker")
str(company)

docs <- apicvm_get(
  "/v1/documents",
  ticker = "VALE3",
  type = "DFP",
  year = 2024,
  perPage = 20
)

ids <- vapply(docs$data, function(d) d$id, character(1))
names <- vapply(docs$data, function(d) d$name, character(1))
data.frame(id = ids, name = names)

Filter FRE risk sections

risks <- apicvm_get(
  "/v1/documents",
  ticker = "VALE3",
  type = "FRE",
  year = 2024,
  name = "FatoresRisco",
  perPage = 20
)

Download one PDF

download_filing <- function(doc_id, dest) {
  request(paste0(base, "/v1/documents/", doc_id, "/file")) |>
    req_headers(Authorization = paste("Bearer", key)) |>
    req_perform(path = dest)
}

if (length(docs$data) > 0) {
  download_filing(docs$data[[1]]$id, "vale3-dfp.pdf")
}

vs pandas

If your team splits R and Python, the same endpoints work in both. See Load Brazil CVM filings into pandas.

Build a simple table of filings

docs_to_df <- function(payload) {
  data.frame(
    id = vapply(payload$data, \(d) d$id, character(1)),
    name = vapply(payload$data, \(d) d$name, character(1)),
    type = vapply(payload$data, \(d) d$type, character(1)),
    stringsAsFactors = FALSE
  )
}

dfp <- docs_to_df(apicvm_get(
  "/v1/documents",
  ticker = "PETR4", type = "DFP", year = 2024, perPage = 20
))
print(dfp)

Auth headers

Authorization: Bearer is preferred. X-API-Key also works. Keep keys in .Renviron, not in committed notebooks. See CVM API authentication.

When R packages that parse ZIPs still help

Local parsers remain useful for bulk accounting panels from Dados Abertos CSVs. Use apicvm when you need a specific issuer PDF or FRE section by ticker. Comparison context: CVM CSV dumps vs API.

Current limitations

  • apicvm returns metadata and files — not a tidy accounting DataFrame of every DFP line.
  • Extraction to page markdown is async (Pro credits), not an R sync helper.
  • Empty lists usually mean “not in corpus yet,” not “issuer has no filings.”

Next steps

Ready to integrate?

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