The Official TypeScript SDK for the SpaceXAI API XAI released the official TypeScript SDK for its SpaceXAI API, published as the npm package @xai-official/sdk and requiring Node.js 22.13 or later. The SDK is experimental, covers the Responses API plus image and video generation, Files, Batch, Voice, tokenization, and model and account lookup, and its interfaces may change before version 1.0, so xAI advises pinning an exact version. The client reads the XAI_API_KEY environment variable, has no runtime dependencies, and blocks browser and Worker use by default to keep API keys server-side. Use Grok from TypeScript with a typed, ESM client built on the SpaceXAI REST API. The SDK has no runtime dependencies and includes streaming, structured output, function tools, image input, image and video generation, file uploads, batch processing, text to speech and transcription, multi-turn conversations, and access to usage and HTTP metadata. Experimental. This SDK is in early development. It currently covers the Responses API, image and video generation, the Files, Batch, and Voice APIs, tokenization, and model and account lookup, and its interfaces may change between releases before 1.0. Pin an exact version and read the changelog https://github.com/xai-org/xai-sdk-ts/blob/main/CHANGELOG.md when upgrading. Feedback and bug reports are welcome in issues https://github.com/xai-org/xai-sdk-ts/issues . - Node.js 22.13 or later - A SpaceXAI API key https://console.x.ai - An ESM project Install the package with your preferred package manager: npm install @xai-official/sdk pnpm add @xai-official/sdk Set your API key in the environment. The client reads XAI API KEY automatically. export XAI API KEY="your-api-key" js import { SpaceXAI } from "@xai-official/sdk"; const client = new SpaceXAI ; const response = await client.responses.create { model: "grok-4.7", input: "Explain why the sky is blue in one sentence.", } ; console.log response.toText ; Keep API keys on the server. The SDK blocks browser and Worker use by default because shipping a secret key to client-side code exposes it to users. Set stream: true to receive output as it's generated. Listen for answer text with on "text" , then await stream.done for the final response: js const stream = await client.responses.create { model: "grok-4.7", input: "Write a short story about a curious robot.", stream: true, } ; const response = await stream .on "text", text = process.stdout.write text .done ; console.log \n${response.usage.total tokens} tokens ; done resolves to the same response object a non-streamed request returns. It rejects if the stream fails or closes before the response completes. Besides "text" , on has helper events for the rest of a response: - "reasoning" for each chunk of reasoning text or reasoning summary - "tool call" for each tool call once its arguments are complete, whether your code or SpaceXAI runs it. Check call.type to tell them apart - "client tool call" for each call that your code runs: your function tools and shell commands - "server tool call" for each call to a tool that SpaceXAI runs, such as web search or code execution - "image" for each finished image generation call, with the base64 image in result - "citation" for each URL citation in the answer Each tool call fires once, when its arguments are complete. For your function tools, that's when to run the function, since nothing has run it yet. To show that a call has started before its arguments arrive, listen for "response.output item.added" . js const response = await stream .on "reasoning", text = process.stderr.write text .on "text", text = process.stdout.write text .on "tool call", call = console.error \n${call.type} ${call.status} .done ; on also takes any server-sent event type, such as "response.completed" , and passes the listener the typed event. Events the SDK doesn't recognize arrive as "unknown" , with the original payload in event.raw . You can also iterate over the stream to handle events in a loop. After the loop, done resolves right away with the final response: js for await const event of stream { if event.type === "response.function call arguments.delta" { process.stdout.write event.delta ; } } const response = await stream.done ; console.log response.toText ; stream.http has the HTTP status, headers, and request IDs as soon as create returns. If you stop consuming a stream early, call await stream.close to cancel its response body. Responses are not stored by default. Use toInput to carry the model output, including encrypted reasoning content, into the next turn. Reuse one prompt cache key across the conversation to improve prompt cache routing: js import { randomUUID } from "node:crypto"; import { type InputItem, SpaceXAI } from "@xai-official/sdk"; const client = new SpaceXAI ; const promptCacheKey = conversation:${randomUUID } ; const input: Array