Access Brazil CVM Filings with Ruby

Need a Ruby CVM filings API client for Brazilian public companies? apicvm is plain HTTPS JSON. Use Net::HTTP, a Bearer token, and the /v1/* routes — there is no official gem.

The problem

Ruby services (Rails apps, Sidekiq workers, Rake jobs) often hit the same friction as other backends:

  • Scrapers that break when the CVM portal UI changes
  • Local ZIP parsers without stable document UUIDs
  • One-off scripts that never become a shared library

A small HTTP wrapper against a fixed contract is easier to keep in a gem or lib/ module.

Setup

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

Ruby 3+ is enough. Examples below use stdlib Net::HTTP and JSON.

Resolve a ticker

require "net/http"
require "json"
require "uri"

base = ENV.fetch("APICVM_URL")
key  = ENV.fetch("APICVM_KEY")

uri = URI("#{base}/v1/companies/resolve")
uri.query = URI.encode_www_form(query: "PETR4", by: "ticker")

req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{key}"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)

List DFP documents

uri = URI("#{base}/v1/documents")
uri.query = URI.encode_www_form(
  ticker: "PETR4",
  type: "DFP",
  year: "2024",
  perPage: "20"
)

req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{key}"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
payload = JSON.parse(res.body)

payload["data"].each do |row|
  puts "#{row["id"]} #{row["name"]}"
end

perPage max is 50. Paginate with page until meta.lastPage. See Paginate and filter CVM documents.

Download a PDF

doc_id = "..." # UUID from list response
uri = URI("#{base}/v1/documents/#{doc_id}/file")

req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{key}"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
File.binwrite("petr4-dfp.pdf", res.body)

File download does not consume extraction credits.

curl cross-check

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

Same contract as Node.js, PHP, and curl.

Errors and rate limits

Map status codes in your HTTP layer: 401 auth, 404 missing document, 429 rate limit. Read X-RateLimit-Remaining when fan-out across tickers. Details: Handle errors and rate limits.

Current limitations

  • Text extraction (POST /v1/document-text-extractions) is async via HTTPS callback — not a sync Ruby string return.
  • Student keys cannot extract markdown (403).
  • perPage max is 50.
  • Corpus coverage depends on ingestion lag; resolve before hard-coding CNPJ.

Next steps

Ready to integrate?

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