Skip to content

Repository files navigation

filingwire

Python client for the FilingWire SEC EDGAR APIs.

Two products, one key:

  • Risk API — every event-bearing 8-K, classified daily into material corporate events (bankruptcy, restructuring and layoffs, delisting risk, M&A, executive departures and appointments, debt acceleration, restatements, auditor changes, cyber incidents, contract changes).
  • Funding API — every Form D private-market fundraising filing, parsed straight from the filing XML: issuer, amount sold, sector, state, investor count, minimum investment.

Every record links back to its source filing on sec.gov.

Install

pip install filingwire

Get a key

A free key takes about a minute and needs no card: https://filingwire.io/free One key reads both products, 1,000 requests a month.

export FILINGWIRE_API_KEY="fw_live_..."

Quickstart

from filingwire import FilingWire

fw = FilingWire()   # or FilingWire("fw_live_...")

# High and critical 8-K events since a date, newest first.
for event in fw.risks.events(min_severity="high", since="2026-08-01", limit=20):
    print(event["event_date"], event["entity_name"], event["severity"])
    print("  ", event["summary"])
    print("  ", event["source_url"])

# Form D raises over $5M in technology this month.
for filing in fw.funding.filings(industry_sector="Technology", min_amount=5_000_000,
                                 since="2026-08-01", limit=20):
    print(filing["entity_name"], filing["total_amount_sold_usd"], filing["state_or_country"])

Listing methods return an iterator that walks pages for you. Pass limit= to stop early; without it, the iterator runs to the end of the result set.

API

Risk (8-K events)

Method What it returns
fw.risks.events(**filters) Iterator over matching events
fw.risks.events_page(page=1, page_size=25, **filters) One page, raw envelope
fw.risks.critical(**filters) High and critical only
fw.risks.latest(**filters) The firehose, newest first
fw.risks.event(accession_number) One event
fw.risks.company(cik) One company's 8-K history
fw.risks.company_by_ticker(ticker) The same, by stock ticker
fw.risks.meta() Row counts and last successful ingest

Filters: event_type, severity, min_severity, since, until, cik, ticker, sector, industry, sic, max_disclosure_lag. min_severity is a floor; severity is exact and wins if you pass both.

Funding (Form D)

Method What it returns
fw.funding.filings(**filters) Iterator over matching filings
fw.funding.filings_page(page=1, page_size=25, **filters) One page, raw envelope
fw.funding.large_raises(**filters) The largest recent raises
fw.funding.latest(**filters) The firehose, newest first
fw.funding.filing(accession_number) One filing
fw.funding.company(cik) Every offering by one issuer
fw.funding.meta() Row counts and last successful ingest

Filters: since, until, sector, industry_sector, state, min_amount, max_amount, security_type, min_investors, max_investors, max_minimum_investment, revenue_range, exemption, submission_type, include_amendments.

Dates accept a datetime.date or a "YYYY-MM-DD" string.

Records are plain dicts

Deliberately. The API adds fields over time, and a typed model would turn every addition into a breaking release of this package. Use .get() for anything you are not certain of.

Pagination

An ingest pass inserts at the top of the newest-first list, so rows can shift while you walk. Pinning a date range helps:

events = fw.risks.events(since="2026-07-01", until="2026-08-01")

But it is not sufficient on its own, because rows arrive backdated: EDGAR publishes day D's index on D+1, and the worker rescans a rolling window, so a row stored today can carry a filed_at from several days ago and land inside a range you pinned before it existed. Measured against the live API: an until=today walk saw the total climb 2,931 → 2,935 with 1 duplicate, and until=yesterday still returned 5 duplicates, because that morning's pass stored 119 rows all dated the previous day.

Dedupe on accession_number, which is the unique key for a filing and holds whatever window you pick. If a walk has to be exact, put until a week back rather than a day back.

Errors and quota

from filingwire import QuotaExceeded, NotFound, AuthError

try:
    filing = fw.funding.filing("0001104659-26-086686")
except NotFound:
    ...
except QuotaExceeded as exc:
    print("slow down for", exc.retry_after, "seconds")

print(fw.quota_remaining, "of", fw.quota_limit, "requests left this month")

AuthError (401/403), BadRequest (400), NotFound (404), QuotaExceeded (429), ServiceUnavailable (5xx), all subclassing FilingWireError. 429s and 5xx are retried with backoff; 4xx are not, because repeating a bad request only spends quota.

There are no overage charges. Hitting the cap refuses the request rather than billing it.

Worth knowing before you build on it

  • Freshness is daily, not real-time. EDGAR publishes its index daily, so nothing here is intraday. Form D is checked several times a day.
  • The 8-K event type comes from the filing's own item codes on about 95% of records. The exception is a filing whose only item is the 8.01 catch-all, where a model classifies it or the row stays other.
  • Severity is a model-assigned triage score, not investment, legal or compliance advice.
  • About a third of events carry event_type: "other". On a 400-row sample that is dividends, NAV notices, shareholder meetings and buybacks, not hidden distress. If you filter to the named types you will not see those rows.
  • Form D has no ticker field, because only about 4% of Form D issuers have one. Pooled investment funds are excluded.
  • No personal data in any structured field. The one exception is the 8-K summary, which quotes the filing, so an executive-departure summary can name the executive who left. That text is verbatim from a public SEC filing.
  • On the free tier, list endpoints return the most recent 30 days. Single-company and single-filing lookups return full history on every plan, including free.
  • Live coverage figures: fw.risks.meta() and fw.funding.meta().

Marketplace keys

If you subscribed through RapidAPI, your key goes through their proxy as X-RapidAPI-Key and this client does not apply. Use their generated snippet, or get a key from filingwire.io/free to use this package.

Development

pip install -e ".[dev]"
pytest

The tests use a mock transport and never touch the network.

Links

License

MIT

About

Python client for the FilingWire SEC EDGAR APIs: Form D private funding and classified 8-K material corporate events.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages