Build a Multi-Ticker CVM Filings Watchlist
A CVM filings watchlist API pattern is simple: keep a ticker list, poll GET /v1/documents on a schedule, and diff against the last seen document.id set. apicvm does not ship a “new filing” webhook — polling is the supported approach.
The persona
- Quant and agent builders tracking a Brazil universe
- Product teams showing “latest filings” for a user portfolio
- Researchers refreshing DFP/ITR after earnings season
The problem
You care about many tickers, not one curl. Without a watchlist loop you either over-fetch (rate limits) or miss documents. Some vendors advertise push webhooks within seconds of publication; apicvm’s contract is request/response + extraction callbacks, not a live CVM firehose.
Solution: poll + diff
Load watchlist tickers
For each ticker (throttle to stay under rate limit):
GET /v1/documents?ticker=...&types=DFP,ITR,FRE&year=current
Diff ids vs local store
Enqueue download/extract for new ids
Sleep until next interval
Example: Python watchlist pass
import os, time, requests
from datetime import datetime
BASE = os.environ["APICVM_URL"]
H = {"Authorization": f"Bearer {os.environ['APICVM_KEY']}"}
WATCH = ["PETR4", "VALE3", "ABEV3", "JBSS3", "RENT3"]
YEAR = datetime.utcnow().year
seen = set() # persist this in Redis/DB in production
def list_docs(ticker):
r = requests.get(
f"{BASE}/v1/documents",
headers=H,
params={"ticker": ticker, "types": "DFP,ITR,FRE", "year": YEAR, "perPage": 50},
)
if r.status_code == 429:
reset = r.json().get("error", {}).get("details", {}).get("resetAt")
time.sleep(5 if not reset else max(1, int(reset) - int(time.time())))
return list_docs(ticker)
r.raise_for_status()
return r.json()["data"]
new_items = []
for t in WATCH:
for d in list_docs(t):
if d["id"] not in seen:
seen.add(d["id"])
new_items.append((t, d["type"], d["name"], d["id"]))
time.sleep(1) # polite spacing inside the 60 req / 60s window
print("new:", len(new_items))
for row in new_items[:10]:
print(row)
Tune time.sleep and batch size to your plan’s rate limit. Standard Student/Pro windows are 60 requests per 60 seconds.
What to store
| Field | Why |
|---|---|
document.id |
Stable primary key for diffs |
ticker, type, year |
Routing / UI |
name, dateRef |
Human label |
hash (if present) |
Optional change detection |
Current limitations
- No native new-filing webhook in v1.
- Extraction callbacks notify page progress for a job you started — they are not market-wide filing alerts.
- Corpus lag means a document can exist on the CVM portal before it appears in apicvm.
Next steps
Ready to integrate?
Get an API key and start querying Brazilian CVM filings programmatically.