Skip to main content

toktik — Python SDK for the TokTik Developer API

Typed Python client for the TokTik Developer API: the full REST data-plane plus a realtime (asyncio) LIVE-event client. Feature parity with @toktikhq/sdk-js; the contract source of truth is @v2/contracts / the served GET /openapi.json.

from toktik import TokTikClient

client = TokTikClient(api_key="ttk_live_...")
board = client.rankings.official(board="hourly", region="VN")
print(board["provenance"])          # the envelope is never stripped
import asyncio
from toktik import TokTikClient, EventFrame

async def main():
    client = TokTikClient(api_key="ttk_live_...")
    async for frame in await client.live.stream(["@creator"]):
        if isinstance(frame, EventFrame):
            print(frame.event, frame.data)          # chat / gift / like / ...

asyncio.run(main())

Install

pip install toktik                # REST only — zero dependencies
pip install "toktik[realtime]"    # adds `websockets` for the realtime client

The REST client speaks HTTP through the standard library, so the data-plane surface pulls in nothing. The realtime client needs a WebSocket implementation; installing the realtime extra provides it, or you can pass your own transport (RealtimeStream(connect=...)).

Design

  • Provenance is never stripped. Data methods return the parsed JSON envelope unchanged — {"data": ..., "provenance": {...}}. For observed (rather than officially published) data, that context is part of the answer. The two documented exceptions match the JS SDK: exports.download returns CSV text, and account.usage is returned directly (no envelope).
  • Errors are surfaced, not swallowed. A non-2xx raises TokTikApiError carrying status, code, request_id and helpers (is_payment_required for 402, is_forbidden for 403, is_rate_limited for 429, retryable). Distinguishing them is the whole point: 402 means buy credits, 403 means the key lacks the scope, 429 means back off.
  • Argument names are snake_case, mapped to the server's wire names. Every route's Fastify schema sets additionalProperties: false, so a wrong query key is a hard 400. The mapping is transcribed from the routes, and a CI parity test asserts every documented data-plane path is covered.
  • The realtime client owns token lifetime, reconnection and resume. A fresh handshake token is minted per connection (expiry becomes a reconnect, not a dead socket); reconnects use exponential backoff with full jitter; and because the gateway keeps no per-connection memory, subscriptions are re-sent on every open. queued / active / offline / unavailable are reported honestly.

REST surface

Namespace Methods Scope
client.rankings official(board, region, limit), movers(board, region, limit), history(board, region, limit, cursor, league_tier), regions(), games(region) rank:read
client.live_pro directory(region, live_only, limit), regions() — the LIVE Pro creator directory live-pro:read
client.recruit list(region, exclude_live_pro, new_only, min_followers, max_coins_30d, min_score_today, sort, limit, cursor), mark(creator_uid, status, note), unmark(creator_uid), marks(status, limit, cursor) rank:read (pool), watchlist:manage (marks)
client.live creator_performance, stream_token, stream live:read / live:stream
client.creators list, get, changes, analysis, following, followers creator:read
client.content creator_videos, video, video_comments content:read
client.gifters list, get, for_creator gifter:read
client.agencies list(region, q, service_type, public_profile_only, sort, limit, offset), get(agency_id), regions() — contact details only on the Agency plan agencies:read
client.trends list(region, type) trend:read
client.exports list, create, get, download export
client.account entitlements, usage keys:manage

Realtime

await client.live.stream(creator_ids) returns a connected RealtimeStream — an async iterator of frames:

  • StatusFrame(creator_id, status, room_id, reason) — subscription lifecycle (queued→active→…, or offline).
  • EventFrame(event, event_id, creator_id, room_id, sequence, room_state, data, provenance) — a LIVE event (chat, gift, like, member, roomUser, social, control, envelope, goodyBag, unknown).
  • ErrorFrame(code, message, retryable) — a server-side subscription error.

subscribe(id) / unsubscribe(id) change the set mid-stream; aclose() (or async with) stops for good and cancels reconnection.

The token is minted from platform-api; its wsUrl points at the API host, which nginx routes to the gateway in production. Driving a local gateway directly, mint the token yourself and pass the gateway URL — see examples/realtime_demo.py.

Development

python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
python -m unittest discover -s tests    # 51 tests, no network
mypy && ruff check src tests

The OpenAPI parity snapshot is generated from @v2/contracts (regenerated + diffed in CI):

npm run build --workspace @v2/contracts
node packages/sdk-python/scripts/gen_openapi_snapshot.mjs

0.3.1

recruit.list(country=…) and the recruit export accept country (the creator's RESOLVED country — what a Recruit country card groups by; region stays the board bucket). Additive, no breaking change.

0.3.0

Adds client.live_pro (directory, regions — LP.4/LP.7) and client.recruit (list, mark, unmark, marks — the recruiting pool + your workspace's marks, EC.1/EC.2); exports.create takes the new recruit dataset with its filters (region, exclude_live_pro, new_only, min_followers, max_coins_30d). Additive, no breaking change.

0.2.0 (breaking)

live.list_sessions and live.get_session were removed — GET /v1/live/sessions answers 410 endpoint_removed since 2026-09-24. exports.create now requires dataset and takes every real export: rankings (board, region, optional game / period), gifters (range_days, optional region / segment), creator_roster, and creator_gifters (creator_unique_id, optional window). live_sessions is no longer a dataset. dataset="agencies" exports TikTok's LIVE agency directory (optional region / query); its contact_* columns exist only on the Agency plan.

Publishing

Releases are tag-driven through .github/workflows/sdk-release.yml:

git tag sdk-python-v0.3.1
git push origin sdk-python-v0.3.1

The release job builds and checks both the sdist and wheel, installs the wheel into a clean virtual environment, and publishes with PyPI Trusted Publishing. The PyPI project must trust this repository, that workflow, and the pypi GitHub environment before the first release.

Known scope limits

  • Response bodies are typed dict (JsonDict), not generated models. The shapes live in @v2/contracts (TypeScript); generating Pydantic models from them was deliberately deferred to avoid silent drift. Method arguments and realtime frames are typed.
  • Sync REST only. An asyncio REST client is not yet provided; the realtime client is async, and it mints its token off the event loop via asyncio.to_thread.

Metadata

Release files for toktik 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for toktik 0.3.1
File Size Uploaded
toktik-0.3.1.tar.gz 31.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for toktik 0.3.1
File Interpreter ABI Platform
toktik-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 54.8 kB

Release files / toktik-0.3.1.tar.gz

Download URL toktik-0.3.1.tar.gz
Size 31.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ac1fbed45fdb40aea5fa529f6e4e01c7f6bc30e3b0e2f5818ce886fa6b8391b1
BLAKE2b-256 checksum
How to use checksums
af4c76946eb22d027a4aec200ca8730760a27452a2e3728b97b00a79edf1c908
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / toktik-0.3.1-py3-none-any.whl

Download URL toktik-0.3.1-py3-none-any.whl
Size 23.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6ebad7ef1ed08b1f7ad41d78c1cfe5916c3a1c7a8ff84e3963d2cdf24d064714
BLAKE2b-256 checksum
How to use checksums
3f5afe33fb085005dcbec4804071729d0f5313b8db121adb76236392c87eb7da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page