TokenSaver SDK
Python client for the TokenSaver API (POST /pipelines/run, RAG, chat sessions, pricing).
Only HTTP transport and response normalization run in this package; all pipeline logic stays on the server.
Get started (public) : the API Reference (examples, parameters, SDK methods) is on the product website — tokensaver.fr/sdk-api — no sign-in required. To obtain API keys and use a workspace, sign up or sign in at platform.tokensaver.fr; the console includes the same reference when you are logged in.
Also : tokensaver.fr — product marketing / positioning. https://api.tokensaver.fr/api/v1 — HTTP API this SDK calls by default (base_url); override base_url only for another deployment.
Installation
pip install tokensaver-sdk
Development inside the monorepo:
cd packages/sdk
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
Maintainers with a clone of the private repository can read the long-form architecture notes at docs/ARCHITECTURE-SDK-TOKENSAVER.md (repo root). That path is not published on PyPI.
Configuration
api_key(required): TokenSaver API key (ts_...).base_url(optional): API base URL; defaulthttps://api.tokensaver.fr/api/v1.provider_api_key(optional): Ephemeral LLM API key sent on everyask/run_pipelinewhen set; overrides organisation keys for that run only; never persisted. You can also passprovider_api_key=on a single call.
LLM providers (hosted vs self-hosted)
On the default public API (base_url omitted or https://api.tokensaver.fr/api/v1), the SDK only sends requests for provider codes listed in API_PIPELINE_LLM_PROVIDERS (same as HOSTED_SAAS_LLM_PROVIDERS: openai, anthropic, google, mistral, grok, deepseek — aligned with the backend SUPPORTED_PROVIDERS and the hosted console). Any other code is rejected client-side with ValidationError / HOSTED_LLM_PROVIDER so mis-typed integrations fail fast.
LLM provider keys (today vs planned): today the backend returns PROVIDER_KEY_MISSING if the organisation has no key for that vendor in Settings → LLM provider keys (and you did not pass provider_api_key on the run). Planned (hosted SaaS): on the public API, standard plans will use platform-managed keys — you will only need your TokenSaver key. Enterprise will use BYOK (your org keys). Spec: monorepo docs/CLES-LLM-HOSTED-ET-BYOK.md.
For a custom base_url (self-hosted or private deployment), the SDK does not apply this hosted allowlist; the server’s catalogue and SUPPORTED_PROVIDERS remain authoritative.
Constants (optional imports): HOSTED_SAAS_LLM_PROVIDERS, API_PIPELINE_LLM_PROVIDERS, DEFAULT_PUBLIC_API_BASE_URL. A provider code outside the hosted set on the default URL raises ValidationError with code HOSTED_LLM_PROVIDER (ERROR_HOSTED_LLM_PROVIDER).
The API also rejects provider / model pairs that are not in the active llm_models catalogue (HTTP 400, LLM_MODEL_NOT_SUPPORTED) — the SDK maps that to ValidationError (ERROR_LLM_MODEL_NOT_SUPPORTED). List allowed pairs with GET /api/v1/llm-reference/models.
from tokensaver_sdk import TokenSaver
ts = TokenSaver(api_key="ts_...")
# Local backend:
# ts = TokenSaver(api_key="ts_...", base_url="http://localhost:8000/api/v1")
# Default LLM key for all runs (optional):
# ts = TokenSaver(api_key="ts_...", provider_api_key="sk-...")
Governance policies (module on/off)
Policies are scoped to the authenticated API key. Inherited org/workspace policies appear in list_governance_policies() but are editable only in the console at that scope.
| Method | Role |
|---|---|
get_pipeline_settings() |
Thresholds, effective_modules, plan_features |
effective_modules() |
Shortcut: use_cache, use_rag, use_compression, use_pii_filter |
patch_pipeline_settings(...) |
Merge thresholds / pii_options / default_model (not module on/off) |
list_governance_policies(kind=...) |
Own + inherited policies, effective_gates |
get_governance_policy(policy_id) |
One key-owned policy |
create_governance_policy(name, kind=..., config=...) |
Enable a module by creating an enabled policy |
update_governance_policy(policy_id, enabled=...) |
Toggle or tune a policy |
delete_governance_policy(policy_id) |
Remove a key-owned policy |
By default, create_governance_policy / update_governance_policy(..., enabled=True) check plan_features (e.g. has_cache) and raise ValidationError (PLAN_CACHE_DISABLED, …) if the plan excludes the module. Pass validate_plan=False to skip the client check.
ts.create_governance_policy(
"Production cache",
kind="cache",
config={"exact_cache": True, "semantic_cache": True, "similarity_threshold": 0.85},
)
assert ts.effective_modules()["use_cache"] is True
ts.update_governance_policy(policy_id, enabled=False)
Typed config: CachePolicyConfig, RagPolicyConfig, CompressionPolicyConfig, PiiPolicyConfig.
Pipeline calls (ask / run_pipeline)
ask() returns a RunResult (.text, .metrics, .trace, .context).
run_pipeline() returns the raw API JSON.
Module on/off is not passed on pipeline calls — use governance policies (see above). Per-run thresholds and options only:
| Parameter | Purpose |
|---|---|
temperature |
LLM temperature (0–2). |
rag_similarity_threshold |
RAG similarity threshold (0–1). |
cache_similarity_threshold |
Semantic cache similarity threshold (0–1). |
compression_level |
Compression level 1–5. |
rag_options |
Dict: document_ids, top_k, query_image_url. |
pii_options |
Dict: engine, strategy, confidence_threshold, entity_types, language, regex_fallback. |
context_layers |
Canonical shape (instructions, knowledge, interaction, token_budget). |
system_prompt, profile_context, workspace_instructions |
Legacy flat fields (if no context_layers). |
provider_api_key |
SDK: ephemeral LLM key for this run; overrides DB keys; not persisted. |
IDE helpers: from tokensaver_sdk import RagOptions, PiiOptions (TypedDict).
result = ts.ask(
"Your question",
provider="openai",
model="gpt-4o",
rag_similarity_threshold=0.55,
rag_options={"document_ids": ["uuid-doc"], "top_k": 8},
)
RAG (documents)
| Method | Role |
|---|---|
rag_list_documents() |
Lists indexed documents in the workspace. |
rag_upload_document(path, …) |
Multipart upload (no wait). Correct MIME per extension (PDF, TXT, MD, CSV, JSON, DOCX). Raises ValidationError (RAG_FILE_NOT_FOUND / RAG_UNSUPPORTED_FILE_TYPE) if the path is missing or the extension is not supported. |
rag_get_document(id) |
Status / metadata. |
rag_wait_document_ready(id, …) |
Wait for ingestion. |
rag_upload_and_wait(path, …) |
Upload + wait. |
rag_ensure_document(path, …) |
Reuses an already ingested file (same file name) or upload + wait. |
Minimal example with a question over an indexed document (any supported type, e.g. PDF or DOCX):
doc = ts.rag_ensure_document("handbook.pdf")
ts.ask(
"What are the key points?",
provider="openai",
model="gpt-4o",
rag_options={"document_ids": [doc["document_id"]]},
)
Constants (aligned with the platform API): RAG_UPLOAD_EXTENSIONS, mime_type_for_rag_filename, ERROR_RAG_UNSUPPORTED_FILE_TYPE.
Chat sessions
from tokensaver_sdk import HISTORY_NONE, HISTORY_LOCAL, HISTORY_SERVER
# Stateless (default for ask: history=HISTORY_NONE)
ts.ask("…", provider="openai", model="gpt-4o", history=HISTORY_NONE)
# Server-side persistence
session = ts.chat.session(history=HISTORY_SERVER, name="My chat")
session.ask("…", provider="openai", model="gpt-4o")
Chat + knowledge (same idea as “+” in the console)
- Index a file (or pick an existing
document_idfromrag_list_documents()). - Either pass
rag_options={"document_ids": [...]}on eachask, or attach IDs once on the session and reuse them on every turn:
session = ts.chat.session(history=HISTORY_SERVER, name="Support")
doc = ts.rag_ensure_document("policy.docx")
session.attach_knowledge(doc["document_id"])
session.ask(
"What is the refund policy?",
provider="openai",
model="gpt-4o",
)
session.clear_knowledge() # optional: stop merging these IDs into later asks
Per-call rag_options["document_ids"] are merged with session attachments (session IDs first, then duplicates removed).
Cost estimate (no LLM call)
ts.estimate_cost(1200, 300, provider="openai", model="gpt-4o")
Errors
from tokensaver_sdk import ERROR_RAG_FILE_NOT_FOUND, ERROR_RAG_UNSUPPORTED_FILE_TYPE
from tokensaver_sdk.errors import (
TokenSaverError,
AuthenticationError,
ProviderKeyMissingError,
QuotaExceededError,
RateLimitError,
ValidationError,
ServerError,
TimeoutError,
)
HTTP errors map to these exceptions. For RAG uploads (rag_upload_document, rag_upload_and_wait, rag_ensure_document when a file is sent), a missing file path on the client raises ValidationError with code="RAG_FILE_NOT_FOUND" (compare to ERROR_RAG_FILE_NOT_FOUND); the raw payload includes "path" among other fields. An unsupported extension raises RAG_UNSUPPORTED_FILE_TYPE before any HTTP call. The API accepts the same document types as the platform (PDF, TXT, MD, CSV, JSON, DOCX).
Tests & quality
pytest
ruff check src tests && ruff format src tests
Useful variables for integration tests: TOKENSAVER_API_KEY, base URL depending on your deployment.
Publishing to PyPI
Maintainers: full checklist, retagging after workflow changes, and troubleshooting → docs/PYPI-SDK-RELEASE.md (read this before pushing sdk-v* tags to avoid CI failures).
- Version: bump
__version__insrc/tokensaver_sdk/__init__.py(single source of truth for the build). - Build & check:
python -m buildthentwine check dist/*(dev deps:pip install -e ".[dev]"). - Upload:
twine upload dist/*(PyPI username:__token__, password: your API token). Try TestPyPI first with--repository testpypi. - CI: after adding the
PYPI_API_TOKENrepository secret, pushing a tagsdk-vX.Y.Zthat matches__version__insrc/tokensaver_sdk/__init__.pytriggers Publish SDK to PyPI (see.github/workflows/publish-sdk-pypi.yml). Example:git tag -a sdk-v0.1.10 -m "Release 0.1.10" && git push origin sdk-v0.1.10. The workflow setsattestations: falsebecause token-based upload is not Trusted Publishing (OIDC); without that, recentgh-action-pypi-publishdefaults can fail even with a valid token.
0.1.11 (PyPI): Governance policy helpers (create_governance_policy, list_governance_policies, get_pipeline_settings, effective_modules, patch_pipeline_settings). Module on/off is policy-driven — use_* flags removed from pipeline requests (422 MODULE_GATE_POLICY_ONLY). Native API docs: GET/POST /sdk/governance/policies, GET/PATCH /sdk/pipeline-settings.
0.1.10 (PyPI): README / PyPI Documentation URL points to public API Reference at tokensaver.fr/sdk-api; clarified get-started flow (website doc vs console for keys).
0.1.9 (PyPI): ChatSession.attach_knowledge / clear_knowledge (RAG document IDs merged into each ask, same idea as the console “+”), multi-format RAG uploads (PDF, TXT, MD, CSV, JSON, DOCX), RAG_UPLOAD_EXTENSIONS, mime_type_for_rag_filename, ERROR_RAG_UNSUPPORTED_FILE_TYPE.
Further reference
- API Reference (public): tokensaver.fr/sdk-api — same content as in the logged-in console.
- Product site: tokensaver.fr — positioning and presentation.
- TokenSaver app: platform.tokensaver.fr — sign in, workspace, API keys.
- HTTP API (SDK default):
https://api.tokensaver.fr/api/v1. - Architecture & decisions: internal to the TokenSaver monorepo (
docs/ARCHITECTURE-SDK-TOKENSAVER.md); not linked here because source repositories are private.
Metadata
Release files for tokensaver-sdk 0.1.11
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tokensaver_sdk-0.1.11.tar.gz | 25.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tokensaver_sdk-0.1.11-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.6 kB
Release files / tokensaver_sdk-0.1.11.tar.gz
| Download URL | tokensaver_sdk-0.1.11.tar.gz |
|---|---|
| Size | 25.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a19c763c2f39987a58f0e7904ebeb91a88ccd304a0d5a1174ecf45aa7395017d
|
|
BLAKE2b-256 checksum How to use checksums |
5c2e35de1093a4564d5719f705a96393cdf56abdbb62e8eea006596f1d150653
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tokensaver_sdk-0.1.11-py3-none-any.whl
| Download URL | tokensaver_sdk-0.1.11-py3-none-any.whl |
|---|---|
| Size | 19.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
29990a0f3aa939559ee7e6967bcc510b63dae705b498a4332f97858093acef7b
|
|
BLAKE2b-256 checksum How to use checksums |
bc6e34713a2d83adc0320db23e9c48cee26bb08ae89cc667123b3785054f416d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|