Official Python SDK for the Clous SEC/EDGAR API — entity-resolved filings, insider & institutional ownership, financials, events, and monitors.
Project description
Clous Python SDK
The official Python client for the Clous SEC/EDGAR API — entity-resolved filings, insider & institutional ownership, structured XBRL financials, a typed business-events feed, grounded Q&A, and standing monitors with webhooks.
pip install clous
Requires Python 3.9+. The only runtime dependency is httpx.
Quickstart
from clous import Clous
client = Clous() # reads CLOUS_API_KEY from the environment
# Search the EDGAR filing index
page = client.filings.search(form_type="8-K", limit=10)
for filing in page:
print(filing["accession"], filing.get("company_name"))
# Structured XBRL financials for one company
revenue = client.financials.get("0000320193", concept="Revenues")
# Grounded Q&A over filings
answer = client.answer("What was Apple's most recent annual revenue?", ticker="AAPL")
print(answer["answer"])
Authentication
Pass your key explicitly or set the CLOUS_API_KEY environment variable:
client = Clous(api_key="sk_live_...")
# or
import os; os.environ["CLOUS_API_KEY"] = "sk_live_..."; client = Clous()
The key is sent as Authorization: Bearer <CLOUS_API_KEY>. The base URL defaults to
https://api.clous.ai and can be overridden with base_url= or the CLOUS_BASE_URL env var.
/v1/sources works without a key.
The response envelope
Every endpoint returns a JSON envelope:
{
"data": [ ... ],
"page": { "limit": 25, "next_cursor": "…", "has_more": true },
"as_of": "2026-06-13T00:00:00Z",
"source": "edgar",
"query_echo": { ... },
"warnings": []
}
The SDK wraps this in a Page object. For the common list case a Page behaves like the data
list (iterate, index, len()), while the envelope metadata and response headers stay available as
attributes:
page = client.events.list(ticker="NVDA", importance="high")
for event in page: # iterate over page.data
print(event["event_type"])
first = page[0] # index into page.data
n = len(page) # number of records on this page
page.next_cursor # cursor for the next page (or None)
page.has_more # bool
page.as_of # snapshot timestamp
page.source # upstream source
page.warnings # list of warnings
page.raw # the full untouched envelope dict
# Response headers
page.request_id # X-Request-Id
page.credits_cost # X-Credits-Cost
page.credits_remaining # X-Credits-Remaining
Single-object endpoints (e.g. client.account(), client.financials.get(...)) expose the object
via page.data; len(page) is then 1.
Pagination
Use ?cursor= / limit= manually, or let the SDK follow page.next_cursor for you with the
iterate(...) helper available on every list resource. It yields individual records across all
pages and accepts an optional max_items cap:
# Manual
page = client.filings.search(form_type="8-K", limit=100)
while page.has_more:
page = client.filings.search(form_type="8-K", limit=100, cursor=page.next_cursor)
# Auto — yields every record, stops after max_items
for filing in client.filings.iterate(cik="0000320193", form_type="8-K", max_items=500):
print(filing["accession"])
limit must be ≤ 100.
Token-efficient projections
Every list/get method accepts fields= (comma-separated dot-paths) or output_schema= (a JSON
Schema dict) to project each record server-side:
client.filings.search(form_type="10-K", fields="accession,company_name,filed_date")
client.events.list(ticker="NVDA", output_schema={"type": "object", "properties": {"event_type": {}, "title": {}}})
Resources & methods
The client groups endpoints by resource. Each search/list method also has an iterate(...)
auto-paginator.
| Resource | Methods |
|---|---|
client.filings |
search, iterate, documents, extract(item=…), insiders, events, subsidiaries, crowdfunding, proxy_votes, briefing |
client.full_text |
search(q=…), iterate |
client.entities |
search / resolve, iterate |
client.insider |
search, iterate, form144, iterate_form144 |
client.ownership |
search, iterate — 13D/13G |
client.holdings |
search, iterate — 13F holdings |
client.managers |
search, iterate — 13F managers |
client.funds |
holdings, providers, iterate_holdings, iterate_providers — N-PORT / N-CEN |
client.advisers |
search, iterate, get(crd) — Form ADV |
client.private_funds / client.private_fund_stats |
search, iterate |
client.broker_dealers / client.form_crs / client.iapd_individuals |
search, iterate |
client.raises |
search, iterate — Form D |
client.financials |
search, iterate, get(cik, concept=…) |
client.financial_statements |
search, iterate |
client.board / client.compensation |
search, iterate |
client.proxy |
officers, iterate_officers — DEF 14A |
client.enforcement / client.litigation / client.nt_late / client.trading_suspensions / client.whistleblower |
search, iterate |
client.cyber_incidents |
search, iterate — 8-K Item 1.05 |
client.patents |
search, iterate — USPTO grants |
client.events |
list, iterate, get(event_id) |
client.monitors |
list, create, get, update, delete |
client.webhooks |
list_endpoints, create_endpoint, list_deliveries |
| top-level | client.account(), client.sources(), client.answer(q, …), client.briefing(accession), client.chat(messages=…) |
Method parameters mirror the REST endpoints. Any extra keyword arguments are passed straight through
as query params (or body fields for POST/PATCH), so new API params work without an SDK upgrade. There
are also raw escape hatches: client.get(path, params=…) and client.post(path, body=…).
Examples
# Insider transactions (Form 4) — purchases over $1M
client.insider.search(ticker="TSLA", trans_code="P", min_value_usd=1_000_000)
# 13F institutional holdings of a security
client.holdings.search(cusip="037833100", min_value=5_000_000)
# Extract Risk Factors from a 10-K
client.filings.extract("0000320193-23-000106", item="1A")
# AI briefing for a filing
brief = client.briefing("0000320193-23-000106")
# Create a monitor that webhooks on high-importance NVDA events
ep = client.webhooks.create_endpoint(url="https://example.com/hook")
mon = client.monitors.create(
name="NVDA watch", target_type="ticker", target_value="NVDA",
materiality="high", webhook_endpoint_id=ep.data["id"],
)
# Stream the events feed
for ev in client.events.iterate(ticker="NVDA", importance="high", max_items=100):
print(ev["event_type"])
OpenAI-compatible endpoint
Clous exposes an OpenAI-compatible chat endpoint. Use the built-in helper:
out = client.chat(messages=[{"role": "user", "content": "Summarize Apple's latest 8-K"}])
print(out["choices"][0]["message"]["content"])
…or point the official openai SDK at Clous directly:
from openai import OpenAI
oai = OpenAI(base_url="https://api.clous.ai/v1", api_key="<CLOUS_API_KEY>")
resp = oai.chat.completions.create(model="clous", messages=[{"role": "user", "content": "…"}])
The Clous SDK also accepts base_url="https://api.clous.ai/v1"; the trailing /v1 is normalized so
resource paths still resolve.
Errors, timeouts, retries
Non-2xx responses raise a typed exception carrying status_code, request_id, message, and the
parsed body:
from clous import APIError, AuthenticationError, RateLimitError, NotFoundError
try:
client.filings.search()
except AuthenticationError:
... # 401
except RateLimitError as e:
... # 429
except NotFoundError:
... # 404
except APIError as e:
print(e.status_code, e.request_id, e.message)
The client times out after 30s (configurable via timeout=) and retries transient failures
(429 + 5xx + network errors) up to max_retries (default 3) with exponential backoff that honors
Retry-After.
Development
pip install -e ".[dev]"
pytest -q
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clous-0.1.0.tar.gz.
File metadata
- Download URL: clous-0.1.0.tar.gz
- Upload date:
- Size: 18.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ac3334a0894ac09510e23cfc8f1c72bd1d20f648afbee4c0ca79190aaf726b3
|
|
| MD5 |
ae35fddf357be401efc6aa680da7d963
|
|
| BLAKE2b-256 |
e942807b8c7d10b169c46778252ec51eaa72219d26f9577559e01e007690e628
|
File details
Details for the file clous-0.1.0-py3-none-any.whl.
File metadata
- Download URL: clous-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0425e719cc822225469a932fcd63616c0f12fc2dd6ce114c5efe6081346a782
|
|
| MD5 |
47dfef3fd94dedb495809a8fd5ae0387
|
|
| BLAKE2b-256 |
de6ade3c7ba6d620dddd11181c7e89e8fc71fc2d4632575d54332fa1b44f1783
|