Server-side Python SDK for TrueSight analytics ingestion
Project description
truesight-sdk
Server-side Python SDK for TrueSight analytics ingestion.
Designed for backends that emit events on behalf of authenticated users (Django, Flask, FastAPI, Airflow DAGs, management commands). Sync by design — if you need async, wrap calls in your own task queue.
Installation
pip install truesight-sdk
Python 3.10+.
Quick Start
Single event
from truesight_sdk import TrueSightClient
client = TrueSightClient(
api_key="ts_server_live_...",
base_url="https://ingest.truesight.example.com",
)
client.track(
event_name="Purchased Lite Pack",
user_id=str(customer.pk),
properties={"plan_slug": "5-30-days", "amount": 1200},
)
User profile update (identify)
client.identify(
user_id=str(customer.pk),
email=customer.email,
properties={
"home_locality": "Andheri",
"favourite_route": "M1",
"weekly_subscription_active": True,
},
)
This upserts the user's row in truesight.user_profiles and also appends a $identify event to the stream for history.
Identify merges into the profile — it does not replace it. The server upserts
user_profilesfield-wise: any field you omit (name,mobile_number, or any key inproperties) is left untouched, andpropertiesis merged key-wise (new values win). So you can send just the fields you want to change. To explicitly clear a value, list it in a$unsetarray insideproperties, e.g.properties={"$unset": ["category"]}(promoted fields match case-insensitively; custom property keys must match exactly).
Bulk profile updates (identify_bulk)
For a one-shot backfill — e.g. "set the email on every customer that's missing one" — use identify_bulk. It takes any iterable of IdentifyEvent, streams it lazily (only chunk_size ops in memory at a time), and auto-chunks to the server's 500-per-call cap. Because the server merges, you only send the fields you're changing:
from truesight_sdk import IdentifyEvent, TrueSightClient
client = TrueSightClient(api_key="ts_server_live_...", base_url="...")
# Fill in just the email — name/mobile/properties already on each profile are preserved.
ops = (
IdentifyEvent(
user_id=str(c.pk),
email=c.email,
event_id=stable_uuid_for(c), # optional: makes re-runs idempotent
)
for c in customers.iterator() # a generator/QuerySet streams; nothing is buffered whole
)
sent = client.identify_bulk(ops) # returns the number of profiles sent
identify_bulk is not transactional — chunks POST sequentially, so if one chunk fails the earlier ones are already applied. Pass a stable event_id per op so a re-run safely converges (retries collapse to the same row).
For continuous, interleaved bulk emission (long-running jobs that mix track and identify), prefer BatchingClient below; for a finite list to push once, identify_bulk is simpler.
Batched ingestion (Airflow / cron / bulk syncs)
For workloads that emit many events in a tight loop, use BatchingClient to amortize HTTP overhead:
from truesight_sdk import BatchingClient, TrueSightClient
inner = TrueSightClient(api_key="ts_server_live_...", base_url="...")
with BatchingClient(inner, batch_size=100, flush_interval_seconds=5.0) as batcher:
for customer in qs.iterator():
batcher.identify(
user_id=str(customer.pk),
properties=build_profile(customer),
)
# Buffers drain on context exit.
BatchingClient is thread-safe; multiple producer threads can call track() / identify() concurrently.
Reading events (admin queries)
The SDK also wraps TrueSight's admin event-query endpoint for read-path consumers:
from truesight_sdk import AdminQueryClient
reader = AdminQueryClient(admin_token="...", base_url="https://admin.truesight.example.com")
page = reader.fetch_events(
project_id="b219fb11-9a63-4843-8126-a3dc05b330a5",
event_name="Purchased Lite Pack",
from_=datetime(2026, 5, 1, tzinfo=timezone.utc),
to=datetime(2026, 5, 28, tzinfo=timezone.utc),
limit=500,
)
# Fetch a single user's profile + stats (email, name, properties,
# first_seen, last_seen, event_count). Raises `NotFound` (404) if the
# user_uid has never been seen by ingest.
profile = reader.fetch_profile(
project_id="b219fb11-9a63-4843-8126-a3dc05b330a5",
user_uid="42",
)
API Keys
Server keys are scoped — they can only call /v1/server/* endpoints. Issue one via the CLI:
truesight projects api-keys create --scope server --label "<your service>"
The plaintext key is returned once at creation time. Store it in your secrets manager.
Error Handling
All errors subclass TrueSightError:
from truesight_sdk import (
AuthError, # 401 — bad / revoked key
Forbidden, # 403 — wrong scope for this endpoint
ValidationError, # 400/422 — payload rejected
RateLimited, # 429 — slow down (after SDK's own retry budget)
ServerError, # 5xx — TrueSight is degraded (after retries)
TrueSightError, # base class — catch this to handle any SDK error
)
try:
client.track("x", user_id="42")
except RateLimited:
schedule_retry(...)
except TrueSightError as exc:
log.exception("truesight ingest failed", request_id=exc.request_id)
Every error carries status_code, request_id (when the server returned one), and response_body for log correlation.
Retry Idempotency
The SDK auto-generates a fresh event_id (UUIDv4) for every event when one isn't supplied. If you need retry idempotency (e.g. inside a Celery task that may run twice), pass an explicit event_id stable across retries:
from truesight_sdk import TrackEvent
from uuid import uuid5, NAMESPACE_URL
stable_id = uuid5(NAMESPACE_URL, f"booking-confirmed:{booking.pk}")
client.track_batch([
TrackEvent(
event_name="Booking Confirmed",
user_id=str(booking.customer_id),
event_id=stable_id,
properties={"booking_id": booking.pk},
),
])
The server dedups on (project_id, event_id) via ClickHouse's ReplacingMergeTree, so retries with the same id collapse to a single row.
Development
# Install in dev mode
pip install -e ".[dev]"
# Run unit tests (no network)
pytest
# Run integration tests against a local TrueSight stack
export TRUESIGHT_BASE_URL=http://localhost:8080
export TRUESIGHT_API_KEY=ts_server_test_...
pytest -m integration
# Lint + typecheck
ruff check src/ tests/
mypy src/
Versioning
Semver. 0.x is pre-1.0 — the public API may shift between minor versions; pin the minor version until 1.0.
License
MIT — see top-level repo.
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 truesight_sdk-0.3.0.tar.gz.
File metadata
- Download URL: truesight_sdk-0.3.0.tar.gz
- Upload date:
- Size: 20.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5dd3911ee001aac8c40e46c616341d927e3b69ab431ec768565f14024107991
|
|
| MD5 |
9abccbd71aee69c270d0705b645a86f8
|
|
| BLAKE2b-256 |
41e8f0cc2120733459997d554df88da40f2f46e61cd12abb0743b08c1a87cb28
|
Provenance
The following attestation bundles were made for truesight_sdk-0.3.0.tar.gz:
Publisher:
publish-python-sdk.yml on komorebitech/cf-truesight
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
truesight_sdk-0.3.0.tar.gz -
Subject digest:
b5dd3911ee001aac8c40e46c616341d927e3b69ab431ec768565f14024107991 - Sigstore transparency entry: 1825727081
- Sigstore integration time:
-
Permalink:
komorebitech/cf-truesight@0168816e1f96b075825d0b81382fb3b3bb3d7419 -
Branch / Tag:
refs/tags/python-sdk-v0.3.0 - Owner: https://github.com/komorebitech
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python-sdk.yml@0168816e1f96b075825d0b81382fb3b3bb3d7419 -
Trigger Event:
push
-
Statement type:
File details
Details for the file truesight_sdk-0.3.0-py3-none-any.whl.
File metadata
- Download URL: truesight_sdk-0.3.0-py3-none-any.whl
- Upload date:
- Size: 17.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9231650555524c7bfab408978c2e26889437f0defe14de329fd1264f5f4d6d4e
|
|
| MD5 |
06f1ce88d60e2c21779b541475a1a94f
|
|
| BLAKE2b-256 |
fc6fba4aa421506438ff109dbaee56d20f8c80da399440614c685d92edbab419
|
Provenance
The following attestation bundles were made for truesight_sdk-0.3.0-py3-none-any.whl:
Publisher:
publish-python-sdk.yml on komorebitech/cf-truesight
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
truesight_sdk-0.3.0-py3-none-any.whl -
Subject digest:
9231650555524c7bfab408978c2e26889437f0defe14de329fd1264f5f4d6d4e - Sigstore transparency entry: 1825727102
- Sigstore integration time:
-
Permalink:
komorebitech/cf-truesight@0168816e1f96b075825d0b81382fb3b3bb3d7419 -
Branch / Tag:
refs/tags/python-sdk-v0.3.0 - Owner: https://github.com/komorebitech
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python-sdk.yml@0168816e1f96b075825d0b81382fb3b3bb3d7419 -
Trigger Event:
push
-
Statement type: