Developer Docs

SDKs

The official JavaScript and Python clients.

Two official clients wrap the same /v1 contract and never strip the provenance envelope. Both are typed; pick the language and stay on it.

SDKPackageVersionTargets
JavaScript / TypeScript@toktik/sdk-js0.2.0v1
Pythontoktik0.1.0v1

JavaScript / TypeScript

@toktik/sdk-js — a typed REST client plus a realtime LIVE-event client that owns its own token lifetime and reconnection.

install
npm i @toktik/sdk-js

Initialise

JavaScript
import { TokTikClient } from "@toktik/sdk-js";

const client = new TokTikClient({ apiKey: process.env.TOKTIK_API_KEY! });

Call the REST API

JavaScript
const board = await client.rankings.official({ board: "hourly", region: "VN" });
console.log(board.data.board);   // the ranked rows
console.log(board.provenance);   // freshness, source, coverageStatus — never stripped

const sessions = await client.live.listSessions({ limit: 20 });

Realtime

JavaScript
import { TokTikClient } from "@toktik/sdk-js";

const client = new TokTikClient({ apiKey: process.env.TOKTIK_API_KEY! });

const stream = await client.live.stream(["@creator_handle"], {
  onStatus: (s) => console.log("status", s.creatorId, s.status),   // queued → active
  onEvent: (frame) => {
    if (frame.event === "gift") {
      const g = frame.data.decoded;
      if (g.repeatEnd) console.log(g.gift?.giftName, (g.gift?.diamondCount ?? 0) * g.repeatCount);
    }
  },
  onError: (e) => console.error(e),
  onReconnect: (attempt) => console.warn("reconnected", attempt)
});

// later: await stream.close();

Errors & retries

JavaScript
import { TokTikClient, TokTikApiError } from "@toktik/sdk-js";

try {
  await client.creators.get("someone");
} catch (err) {
  if (err instanceof TokTikApiError) {
    if (err.isPaymentRequired) {/* 402 — top up credits */}
    else if (err.status === 403) {/* missing scope */}
    else if (err.retryable) {/* 429 / 5xx — back off and retry */}
  }
}

Python

toktik — the REST client is dependency-free (standard-library HTTP); the realtime client is asyncio and needs the realtime extra.

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

Initialise

Python
from toktik import TokTikClient

client = TokTikClient(api_key="ttk_live_...")

Call the REST API

Python
board = client.rankings.official(board="hourly", region="VN")
print(board["data"]["board"])    # the ranked rows
print(board["provenance"])       # freshness, source, coverageStatus

sessions = client.live.list_sessions(limit=20)

Realtime

Python
import asyncio
from toktik import TokTikClient

async def main():
    client = TokTikClient(api_key="ttk_live_...")
    async for frame in await client.live.stream(["@creator_handle"]):
        if frame.type == "status":
            print("status", frame.creator_id, frame.status)
        elif frame.type == "event" and frame.event == "gift":
            g = frame.data["decoded"]
            if g.get("repeatEnd"):
                print(g["gift"]["giftName"], g["gift"]["diamondCount"] * g["repeatCount"])

asyncio.run(main())

Errors & retries

Python
from toktik import TokTikApiError

try:
    client.creators.get("someone")
except TokTikApiError as err:
    if err.is_payment_required:   # 402 — top up credits
        ...
    elif err.is_forbidden:        # 403 — missing scope
        ...
    elif err.retryable:           # 429 / 5xx — back off and retry
        ...

Namespaces

Both clients expose the same namespaces over the same scopes:

NamespaceJavaScriptPythonScope
rankingsofficial, derivedofficial, derivedrank:read
livelistSessions, getSession, creatorPerformance, streamToken, streamlist_sessions, get_session, creator_performance, stream_token, streamlive:read / live:stream
creatorslist, get, changes, analysis, following, followerslist, get, changes, analysis, following, followerscreator:read
contentcreatorVideos, video, videoCommentscreator_videos, video, video_commentscontent:read
gifterslist, get, forCreatorlist, get, for_creatorgifter:read
trendslistlisttrend:read
exportslist, create, get, downloadlist, create, get, downloadexport
accountentitlements, usageentitlements, usagekeys:manage

Recipes

Common tasks, in both languages. Each is a real call sequence against the shipped surface.

Poll a leaderboard every hour and store it

A cron job that pulls the official board and persists the rows with their provenance.

const { data, provenance } = await client.rankings.official({ board: "hourly", region: "VN" });
await db.saveBoard(data.board, provenance.observedAt);

Watch one creator's gifts in realtime

Subscribe to a single creator and total each finished gift streak.

const stream = await client.live.stream(["@creator_handle"], {
  onEvent: (f) => {
    if (f.event === "gift" && f.data.decoded.repeatEnd) {
      const g = f.data.decoded;
      console.log(g.gift?.giftName, (g.gift?.diamondCount ?? 0) * g.repeatCount);
    }
  }
});

Export sessions to CSV

Kick off a bulk export, poll until it is ready, then download the CSV text.

const job = await client.exports.create({ dataset: "live_sessions", format: "csv" });
// poll client.exports.get(job.id) until status is ready, then:
const csv = await client.exports.download(job.id);   // CSV text, not JSON

Versioning

Both SDK lines target the v1 API. The API is versioned in its path (/v1) and only ever grows compatibly within a major — see Versioning. Pin the SDK version in your lockfile; upgrading within the v1 line is additive.