Cookbook

Cookbook

Complete, runnable recipes for building on AI Hub, from a first request to a coding agent.

Each recipe is a complete program you can copy and run. Every example reads its settings from three environment variables and has no default model:

bash
# Copy to .env (never commit it) or export these in your shell.
# AI Hub public API base URL.
TOKENHUB_BASE_URL=https://tokenhub-api.belive.sg/api/v1
TOKENHUB_API_KEY=sk-tokenhub-…
# An exact model id from GET $TOKENHUB_BASE_URL/models. Tool calling needs a model whose
# supported_parameters include "tools".
TOKENHUB_MODEL=

Download and configure

Install Python 3 or Node 22 and download the complete examples from the recipe archive. The archive has the files shown below, including the browser app and local stream checks. Choose an exact model ID from the public catalogue and export your inference key from a secret store.

bash
curl --fail "https://aihub.belive.sg/docs/examples/tokenhub.zip" -o tokenhub-examples.zip
unzip tokenhub-examples.zip
cd tokenhub-examples
cp .env.example .env
# Edit .env: set TOKENHUB_API_KEY and TOKENHUB_MODEL.
# Keep .env local. Scripts read process environment, not the .env file itself.
set -a
. ./.env
set +a
# Use the API base for the environment shown by this docs site.
export TOKENHUB_BASE_URL="https://tokenhub-api.belive.sg/api/v1"

Recipes

Recover an accepted job

A timeout or 5xx can occur after work starts. Keep the returned job ID and the original supported idempotency key/body pair. The recipe below only reads an existing status resource; it never submits generation. Set TOKENHUB_JOB_PATH to that job's returned status path. Inspect terminal failures before considering new work.

bash
export TOKENHUB_JOB_PATH="/api/v1/jobs/$TOKENHUB_JOB_ID"
node --experimental-strip-types troubleshooting/poll-job.ts
typescript
// Read an existing job. This program never submits generation or retries a submission.
// node --experimental-strip-types troubleshooting/poll-job.ts
const base = process.env.TOKENHUB_BASE_URL;
const apiKey = process.env.TOKENHUB_API_KEY;
const jobPath = process.env.TOKENHUB_JOB_PATH;
if (!base || !apiKey || !jobPath) throw new Error("Set TOKENHUB_BASE_URL, TOKENHUB_API_KEY and TOKENHUB_JOB_PATH to an existing job path");
const root = new URL(base.endsWith("/") ? base : base + "/");
const url = new URL(jobPath, root);
// Never forward the key to a different origin, signed storage URL, or arbitrary resource.
if (url.origin !== root.origin || !/^\/(?:api\/)?v1\/(?:chat\/jobs|jobs|videos|audio\/(?:generations|transcriptions|speech\/jobs))\/[^/]+$/.test(url.pathname)) {
  throw new Error("Use an existing AI Hub job status path on the configured API host");
}
for (let attempt = 0; attempt < 30; attempt++) {
  const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${apiKey}` }, signal: AbortSignal.timeout(30_000), redirect: "error" });
  if (!response.ok && ![429, 500, 502, 503].includes(response.status)) throw new Error(`Job lookup refused (${response.status}); check the job id and key`);
  if (response.ok) {
    const job = await response.json();
    if (["failed", "cancelled", "canceled"].includes(job.status)) throw new Error(`Job ${job.id ?? ""} ended with ${job.status}; inspect its error before any new submission`);
    if (["completed", "succeeded"].includes(job.status)) { console.log(JSON.stringify(job, null, 2)); break; }
  }
  if (attempt === 29) throw new Error("Polling limit reached; keep the existing job id and resume its lookup later");
  const hint = response.headers.get("Retry-After");
  const seconds = hint && /^\d+$/.test(hint) ? Number(hint) : 2 ** Math.min(attempt, 4);
  await new Promise((resolve) => setTimeout(resolve, Math.min(Math.max(seconds, 1), 30) * 1000));
}
export {};

Use the endpoint index for the operation's polling route, protocol, schema and availability boundary, and Errors for safe recovery. Use the client-specific guides for known framework and desktop boundaries.

For agents

Every page here is also plain Markdown: add /markdown after /docs, as in /docs/markdown/first-request. The index of all pages is /llms.txt.