Orchestrate Brazil CVM Filings with Temporal

Want Temporal CVM filings jobs that refresh Brazilian DFP/ITR/FRE on a schedule? apicvm is the HTTP source; Temporal owns retries, schedules, and worker isolation.

The problem

Coverage teams need durable retries when listing filings across dozens of tickers. Cron shells lose state; Temporal activities can checkpoint per issuer.

Activity: list ITR

import os, requests

BASE = os.environ["APICVM_URL"]
H = {"Authorization": f"Bearer {os.environ['APICVM_KEY']}"}

def list_itr(ticker: str, year: int):
    return requests.get(
        f"{BASE}/v1/documents",
        headers=H,
        params={"ticker": ticker, "type": "ITR", "year": year, "perPage": 50},
    ).json()["data"]

Activity: download PDF

def download_file(document_id: str, dest: str):
    r = requests.get(
        f"{BASE}/v1/documents/{document_id}/file",
        headers=H,
        stream=True,
    )
    r.raise_for_status()
    with open(dest, "wb") as f:
        for chunk in r.iter_content(65536):
            f.write(chunk)

Download does not consume extraction credits.

Optional: async extraction

POST /v1/document-text-extractions returns 202 and delivers markdown pages to your HTTPS callback. Temporal should not poll a job-status endpoint — v1 has none. Correlate by documentId in the callback payload.

curl smoke test

curl -H "Authorization: Bearer $APICVM_KEY" \
  "$APICVM_URL/v1/documents?ticker=PETR4&type=DFP&year=2024&perPage=20"

Compare with Airflow, Prefect, and Dagster.

Current limitations

  • No real-time material-fact stream in MVP scope
  • Rate limits apply per API key (X-RateLimit-* headers)
  • Empty lists mean "not in corpus yet", not "never filed"

Next steps

Ready to integrate?

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