ksapi — Python SDK Quickstart
The official Python client for the Knowledge Stack API. OpenAPI Generator
7.26.0 generates one HTTPX2 package with both async and blocking methods.
The per-endpoint reference is generated alongside the package under docs/.
Install
pip install ksapi
Async calls and authentication
Mint an API key in the app and pass it as access_token. Requests send
Authorization: Bearer <key>. Point the client at your self-hosted deployment:
import asyncio
import ksapi
from ksapi.api.documents_api import DocumentsApi
config = ksapi.Configuration(
host="https://api.your-host.example",
access_token="sk-user-...",
)
async def main():
async with ksapi.ApiClient(config) as client:
page = await DocumentsApi(client).list_documents(limit=10)
print(page.total, "documents")
asyncio.run(main()) # In an existing event loop, await main() instead.
Browser/session callers can use Configuration(api_key={"cookieAuth": token}, host=...) or client.set_default_header("Cookie", f"ks_uat={token}").
Reuse the client on its owning event loop, and close it with async with or
await client.close() after its requests finish.
Blocking calls
The same API classes expose _sync variants. Existing blocking integrations
must rename calls such as list_documents() to list_documents_sync():
from ksapi.sync_helper import run_sync
client = ksapi.ApiClient(config)
try:
page = DocumentsApi(client).list_documents_sync(limit=10)
print(page.total, "documents")
finally:
run_sync(client.close())
The generated sync helper uses a background event loop; closing through that
helper keeps cleanup on the same loop. ApiClient has no synchronous context
manager. Use separate client instances for sync and async use, and never call
_sync methods from async code: they block the caller's event loop.
The additional method families are operation_sync_with_http_info() and
operation_sync_without_preload_content().
Ingest a document and wait until it is searchable
Upload returns before ingestion completes. Poll the active version's pipeline status before searching. This example assumes an existing async client:
from pathlib import Path
from uuid import UUID
async def ingest(client, parent_path_part_id: UUID):
docs = DocumentsApi(client)
created = await docs.ingest_document(
file=("contract.pdf", Path("contract.pdf").read_bytes()),
path_part_id=parent_path_part_id,
name="contract.pdf",
)
while True:
version = (await docs.get_document(created.document_id)).active_version
metadata = version.system_metadata if version else None
state = metadata.pipeline_state if metadata else None
if state and state.status in ("completed", "failed"):
return state.status
await asyncio.sleep(2)
Ask the agent
from ksapi.api.agent_api import AgentApi
from ksapi.models.ask_request import AskRequest
async def ask(client):
answer = await AgentApi(client).agent_ask(
AskRequest(prompt="What are the renewal terms?", output_language="en"),
_request_timeout=600.0,
)
return answer.text
Use output_language="zh" for Simplified Chinese. HTTPX2 request timeouts bound
individual network phases, not the total operation. Use asyncio.timeout()
when an async caller needs a total deadline. The generator defaults to 300
seconds per phase; long operations can supply an explicit _request_timeout.
Cancellation stops the local wait; it does not undo an accepted server mutation.
Stream chat responses (SSE)
Generated methods buffer bodies, including without_preload_content variants.
For SSE or large binary downloads, use an HTTPX2 streaming client. Raw responses
from generated methods are HTTPX2 responses (status_code, content,
await aread(), await aclose()), not urllib3 responses.
import httpx2
async def stream_thread(host: str, api_key: str, thread_id: str):
headers = {"Authorization": f"Bearer {api_key}"}
async with httpx2.AsyncClient(base_url=host, headers=headers, timeout=60) as http:
async with http.stream("GET", f"/v1/threads/{thread_id}/stream") as response:
response.raise_for_status()
async for line in response.aiter_lines():
if not line.startswith("data:"):
continue
payload = line[len("data:"):].strip()
if payload == "[DONE]":
return
yield payload
Errors
Generated ApiException subclasses expose status and the response body.
Error bodies contain detail, a machine-readable code, and request_id;
branch on the code and quote the request ID when reporting an error.
Transport failures raise HTTPX2 exceptions such as httpx2.RequestError.
from ksapi.exceptions import NotFoundException
from uuid import UUID
async def lookup(client, document_id: UUID):
try:
return await DocumentsApi(client).get_document(document_id)
except NotFoundException as exc:
print(exc.status, exc.body)
Metadata
Release files for ksapi 3.23.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ksapi-3.23.0.tar.gz | 575.7 kB | Without provenance | Details for ksapi-3.23.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ksapi-3.23.0-py3-none-any.whl | Python 3 | none | any | Details for ksapi-3.23.0-py3-none-any.whl |
Total release size: 2.1 MB
Release files / ksapi-3.23.0.tar.gz
| Download URL | ksapi-3.23.0.tar.gz |
|---|---|
| Size | 575.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ac0c41d9a2c8c772611353f66c9929a91a106e6c23c7cf8b2f963a99b3e21cd3
|
|
BLAKE2b-256 checksum How to use checksums |
f895ee278a7b11e52c26a102ec676df457d50fde1633a64beaba72382dcb37a0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.14.9
|
Release files / ksapi-3.23.0-py3-none-any.whl
| Download URL | ksapi-3.23.0-py3-none-any.whl |
|---|---|
| Size | 1.5 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
33fbfbf0f21f2b7de17b9e868fec6abbbad3da78e3a9e4851a403252bdbaac45
|
|
BLAKE2b-256 checksum How to use checksums |
9aa291f4e5cd7700f2fd51ec6ac97b962b9e110bdd46f932901a511fa5375991
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.14.9
|
Security for ksapi 3.23.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.