TypeScript SDK

@joytoken/client-sdk-ts is a type-safe client for JoyToken’s public developer API. It is designed for server-side JavaScript runtimes: Node.js services, Next.js route handlers, workers, and agent runtimes.

Why use the TypeScript SDK

The SDK gives you a small layer over JoyToken’s API without changing the underlying Chat Completions contract.

BenefitWhat it does
Typed requestsChatCompletionRequest, ChatMessage, ChatTool, and model list types
Auth handlingAdds Authorization: Bearer $JOY_TOKEN_API_KEY when an API key is configured
Streaming helperParses data: SSE records and yields JSON chunks
Model list helperCalls GET /api/v1/models
API errorsThrows JoyTokenAPIError with status, request ID, response headers, and body

Install

$pnpm add @joytoken/client-sdk-ts

Configure

client.ts
1import { JoyTokenClient } from "@joytoken/client-sdk-ts";
2
3export const joytoken = new JoyTokenClient({
4 apiKey: process.env.JOY_TOKEN_API_KEY,
5});

Defaults:

OptionDefault
apiKeyprocess.env.JOY_TOKEN_API_KEY
apiBaseUrlprocess.env.JOY_TOKEN_API_BASE_URL or https://api-dev.joytokens.ai
openAIBaseUrlprocess.env.JOY_TOKEN_OPENAI_BASE_URL or ${apiBaseUrl}/openai/v1
fetchglobalThis.fetch
timeoutMsNo SDK timeout unless configured

Chat Completions

chat.ts
1const completion = await joytoken.chat.completions.create({
2 model: "auto",
3 tier: "standard",
4 messages: [
5 { role: "system", content: "You are concise." },
6 { role: "user", content: "Explain JoyToken in one sentence." },
7 ],
8});
9
10console.log(completion.choices[0]?.message?.content);

Streaming

stream.ts
1const stream = joytoken.chat.completions.stream({
2 model: "auto",
3 messages: [{ role: "user", content: "Write a short release note." }],
4});
5
6for await (const chunk of stream) {
7 if (chunk.choices?.length) {
8 process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
9 }
10
11 if (chunk.metadata) {
12 console.log("metadata", chunk.metadata);
13 }
14}

JoyToken appends a metadata event near the end of streaming responses. Treat chunks with metadata as observability data, not assistant text.

Models

models.ts
1const models = await joytoken.models.list();
2
3for (const model of models.data) {
4 console.log(model.id, model.name);
5}

Error handling

errors.ts
1import { JoyTokenAPIError } from "@joytoken/client-sdk-ts";
2
3try {
4 await joytoken.chat.completions.create({
5 model: "auto",
6 messages: [{ role: "user", content: "ping" }],
7 });
8} catch (error) {
9 if (error instanceof JoyTokenAPIError) {
10 console.error(error.status, error.requestId, error.body);
11 throw error;
12 }
13
14 throw error;
15}

Next.js route example

app/api/chat/route.ts
1import { JoyTokenClient } from "@joytoken/client-sdk-ts";
2
3const joytoken = new JoyTokenClient({
4 apiKey: process.env.JOY_TOKEN_API_KEY,
5 defaultHeaders: {
6 "X-Request-ID": "nextjs-chat",
7 },
8});
9
10export async function POST(req: Request) {
11 const { messages } = await req.json();
12
13 const completion = await joytoken.chat.completions.create({
14 model: "auto",
15 messages,
16 });
17
18 return Response.json(completion);
19}

Keep JoyToken API keys on the server side. Do not expose JOY_TOKEN_API_KEY in browser code.