streamgine — Python SDK
Real-time webhook events for California corporate registry changes. Get notified the moment a company is added, updated, or removed — as structured JSON diffs, delivered to your endpoint.
Product: diff.streamgine.com · Docs: docs.md · Coverage: California · Use cases: risk monitoring, AI agents
Install
pip install streamgine
Requires Python 3.10+. One dependency: httpx.
Quickstart
Get your credentials from diff.streamgine.com/account, then:
from streamgine import diff
diff.configure("diff-streamgine-credentials.json")
# or: source diff-streamgine-env.sh then diff.configure()
client = diff.DiffClient()
1. Confirm your webhook is reachable
Before wiring real events, send yourself a test heartbeat:
client.register_test(callback_url="https://your-agent.example/webhooks/diff")
You'll start receiving a signed test event every second on topic diff-event.test:
{ "action": "INSERT", "after": { "test": "success" } }
Filter on event.is_test_heartbeat to ignore these once you're live.
2. Subscribe to real events
client.register(
match={"state": "CA", "principal_city": "San Francisco"},
actions=["INSERT"],
callback_url="https://your-agent.example/webhooks/diff",
)
INSERT = new company, UPDATE = changed, DELETE = removed. Omit actions to receive all three.
3. Search current company records
Webhooks deliver changes over time. search() returns current snapshots:
result = client.search(query={"match": {"principalCity": "San Francisco"}}, size=10)
for company in result["entities"]:
print(company.get("entity_name"), company.get("entity_number"))
4. Verify inbound webhooks (required)
Always verify raw request bytes before trusting the payload:
def handle_webhook(raw_body: bytes, signature: str | None):
try:
event = diff.verify_webhook(raw_body, signature)
except diff.WebhookVerificationError:
return 401, {"error": "invalid signature"}
print(event.action, event.entity_id, event.after)
return 200, {"ok": True}
FastAPI
from fastapi import FastAPI, Header, Request, Response
from streamgine import diff
app = FastAPI()
@app.on_event("startup")
def setup():
diff.configure()
@app.post("/webhooks/diff")
async def diff_webhook(
request: Request,
response: Response,
x_diff_signature: str | None = Header(default=None, alias="X-Diff-Signature"),
):
raw = await request.body()
try:
event = diff.verify_webhook(raw, x_diff_signature)
except diff.WebhookVerificationError:
response.status_code = 401
return {"error": "invalid signature"}
return {"ok": True, "entity_id": event.entity_id}
Flask
from flask import Flask, request
from streamgine import diff
app = Flask(__name__)
diff.configure()
@app.post("/webhooks/diff")
def webhook():
try:
event = diff.verify_webhook(
request.get_data(),
request.headers.get("X-Diff-Signature"),
)
except diff.WebhookVerificationError:
return {"error": "invalid signature"}, 401
return {"ok": True, "action": event.action}
Security
| Practice | How this client helps |
|---|---|
| Verify every webhook | verify_webhook() uses timing-safe comparison on the raw body |
| Match the signing algorithm | HMAC-SHA256(secret, raw_json_bytes) → header X-Diff-Signature: sha256=<hex> |
| Parse only after verifying | Tampered bodies fail before an event object is built |
| HTTPS by default | TLS verification is on unless explicitly disabled |
| Keep secrets in one place | One configure() call from a JSON file or env vars — never pass keys directly to client constructors |
Never log your signing secret, and never skip verification in production.
Credentials
Download from diff.streamgine.com/account:
| File | Then call |
|---|---|
diff-streamgine-credentials.json |
diff.configure("diff-streamgine-credentials.json") |
diff-streamgine-env.sh |
source diff-streamgine-env.sh then diff.configure() |
Call configure() once at startup — every DiffClient() and verify_webhook() call reads from it.
API surface (streamgine.diff)
| Symbol | Role |
|---|---|
configure() |
Load credentials once (file path or environment) |
get_config() |
Read the active configuration |
DiffClient |
register(), register_test(), health(), get_state(), search() |
verify_webhook() |
Verify a webhook signature and return a parsed event |
WebhookEvent |
Parsed action, entity_id, and after fields |
WebhookVerificationError |
Raised on invalid or missing signatures |
Links
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 streamgine-1.0.1.tar.gz.
File metadata
- Download URL: streamgine-1.0.1.tar.gz
- Upload date:
- Size: 16.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
760b3ae09cba52d686f6a2edee39afb0c0552b320348fcc38b8d9baaced6f460
|
|
| MD5 |
d9523e799c22fb29a381fb39dbc07016
|
|
| BLAKE2b-256 |
c5f6e199f0878f9778718e6e0e7261729fcbcd58e9bf3c863739e6db450397c1
|
Provenance
The following attestation bundles were made for streamgine-1.0.1.tar.gz:
Publisher:
publish-python.yml on scurtutech/diff-events-service
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
streamgine-1.0.1.tar.gz -
Subject digest:
760b3ae09cba52d686f6a2edee39afb0c0552b320348fcc38b8d9baaced6f460 - Sigstore transparency entry: 2733319609
- Sigstore integration time:
-
Permalink:
scurtutech/diff-events-service@060bd4796f884fc81b8d4d97f2e2daa055f4db42 -
Branch / Tag:
refs/tags/python-v1.0.1 - Owner: https://github.com/scurtutech
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@060bd4796f884fc81b8d4d97f2e2daa055f4db42 -
Trigger Event:
release
-
Statement type:
File details
Details for the file streamgine-1.0.1-py3-none-any.whl.
File metadata
- Download URL: streamgine-1.0.1-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbeaf277a2ee9e7d90c82afa45197ccf31ccf705a0f35f0bcc983969e3b6da6d
|
|
| MD5 |
4d527d49bdde0f62de4adc05f65cceaf
|
|
| BLAKE2b-256 |
53ed3ab85cf5bf707654c736c18fc9ec2397dc298806d57094b0c92190004e72
|
Provenance
The following attestation bundles were made for streamgine-1.0.1-py3-none-any.whl:
Publisher:
publish-python.yml on scurtutech/diff-events-service
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
streamgine-1.0.1-py3-none-any.whl -
Subject digest:
bbeaf277a2ee9e7d90c82afa45197ccf31ccf705a0f35f0bcc983969e3b6da6d - Sigstore transparency entry: 2733319633
- Sigstore integration time:
-
Permalink:
scurtutech/diff-events-service@060bd4796f884fc81b8d4d97f2e2daa055f4db42 -
Branch / Tag:
refs/tags/python-v1.0.1 - Owner: https://github.com/scurtutech
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@060bd4796f884fc81b8d4d97f2e2daa055f4db42 -
Trigger Event:
release
-
Statement type: