TypeScript SDK.
@gpuai/sdk is the official typed TypeScript client, generated from the same OpenAPI spec as the REST API, so every endpoint has a typed method and every response has a generated interface. Node 22+ is the tested floor, and the package is CJS-primary: require() resolves under plain node with no bundler and no build step.
It covers the whole public surface: GPU types and pricing, instances, SSH keys, templates, fine-tuning, serverless inference, usage, billing, and webhooks. Bundlers (webpack, vite, esbuild, …) automatically pick up the ESM build via the module field.
§ 09.1Install¶
The package is published to npm as @gpuai/sdk.
npm install @gpuai/sdk§ 09.2Base URL and authentication¶
| Base URL | https://api.gpu.ai/v1 |
| Auth | Authorization: Bearer gpuai_live_… |
Get a key with gpu login (it stores a gpuai_live_… key in ~/.config/gpu/credentials.json) or mint one in the dashboard. Pass it as accessToken on the Configuration and the SDK sets the Authorization header for you.
Read-only catalog endpoints (/v1/gpu-types, /v1/pricing) need no key at all — the quick start below runs without credentials.
§ 09.3Quick start¶
Read-only, no API key, nothing billable — list the GPU models GPU.ai carries and the current cheapest offerings. Save as quickstart.js and run it with node quickstart.js:
const { Configuration, GpuTypesApi, PricingApi } = require('@gpuai/sdk');
const BASE_URL = 'https://api.gpu.ai/v1';
async function main() {
const cfg = new Configuration({ basePath: BASE_URL });
// What GPU models are available?
const types = await new GpuTypesApi(cfg).listGpuTypes({ limit: 5 });
for (const t of types.data) {
console.log(`${t.gpuType.padEnd(12)} vram=${t.vramGb}GB`);
}
// What do they cost right now?
const pricing = await new PricingApi(cfg).listPricing({ limit: 5 });
for (const p of pricing.data) {
console.log(
`${p.gpuType.padEnd(12)} x${p.gpuCount} ${p.region.padEnd(12)} ` +
`$${p.pricePerHour}/hr available=${p.available}`
);
}
}
main();Field names are camelCase on the TypeScript side (gpu_type on the wire is gpuType here); method names mirror the spec's operationIds directly (listGpuTypes, listPricing).
Every list endpoint is cursor-paginated: the response carries data plus a nextCursor that is null on the last page. Pass it back as cursor to walk forward.
§ 09.4Authenticated calls¶
Set accessToken on the Configuration to reach anything account-scoped. This example lists your SSH keys — still a read, still nothing billable — and takes the key from the environment so no credential is ever pasted into source:
const { Configuration, SshKeysApi } = require('@gpuai/sdk');
const BASE_URL = 'https://api.gpu.ai/v1';
async function main() {
const cfg = new Configuration({
basePath: BASE_URL,
accessToken: process.env.GPUAI_API_KEY, // e.g. from `gpu login`
});
const keys = await new SshKeysApi(cfg).listSshKeys({ limit: 5 });
console.log(`${keys.data.length} ssh key(s)`);
for (const k of keys.data) {
console.log(` ${k.name}`);
}
}
main();export GPUAI_API_KEY=gpuai_live_...
node authed.jsThe same pattern reaches the rest of the API — InstancesApi, TemplatesApi, FineTuningApi, InferenceApi, UsageApi, BillingApi, WebhooksApi. Each API class's methods are documented in the generated tree.
§ 09.5TypeScript and ESM¶
The package ships its own type declarations (types → dist/index.d.ts), so the same entry point is fully typed. In a .ts file, TypeScript's typed-CJS import form keeps you on the same CommonJS path:
import GpuAi = require('@gpuai/sdk');
async function main(): Promise<void> {
const api = new GpuAi.GpuTypesApi(
new GpuAi.Configuration({ basePath: 'https://api.gpu.ai/v1' })
);
const page: GpuAi.GPUTypePage = await api.listGpuTypes({ limit: 5 });
page.data.forEach((t: GpuAi.GPUType) => {
console.log(`${t.gpuType} vram=${t.vramGb}GB`);
});
}
main();If your project is compiled by tsc or a bundler (vite, webpack, esbuild, …), the standard ESM syntax — import { Configuration } from '@gpuai/sdk' — works too: tsc with module: commonjs emits the require above, and bundlers pick up the ESM build through the module field.
§ 09.6Errors¶
A non-2xx response rejects with ResponseError, which carries the raw fetch Response:
const { Configuration, SshKeysApi, ResponseError } = require('@gpuai/sdk');
try {
// a well-formed id that does not exist on this account
await new SshKeysApi(cfg).getSshKey({ id: '00000000-0000-0000-0000-000000000000' });
} catch (e) {
if (e instanceof ResponseError) {
console.log(`api error ${e.response.status}:`, await e.response.text());
} else {
throw e;
}
}api error 404: {"type":"https://api.gpu.ai/errors/not_found","title":"Not Found",
"status":404,"detail":"SSH key not found","code":"not_found","request_id":"…"}The body is an RFC 9457 problem document; request_id is what to quote in a support email.
§ 09.7Versioning — pre-1.0 convention¶
The SDK is versioned independently of the API (the API is v1 and stays v1). While the SDK is on 0.x, it follows this convention:
- Breaking change → minor bump
- Everything else — new endpoints, new fields, doc changes → patch bump
npm's caret operator already enforces exactly this at 0.x: a caret range on a 0.x release (^0.<minor>.<patch>) accepts patch releases only and will not pull a minor bump, so the default npm install range keeps you on non-breaking updates. The Python package needs an explicit pin to get the same protection — pip has no equivalent rule.
Breaking releases are called out in a ⚠ Breaking section of the GitHub Release notes for the release tag — at 0.x the version number alone will not warn you, so the release notes are the channel to read.
1.0.0 is a deliberate stability promotion, made as a human call — it never happens automatically by rolling over from 0.x.
§ 09.8Related¶
- Python SDK — the same surface for Python.
- The gpu CLI — the command-line client.
- Inference API — OpenAI-compatible chat, embeddings, image and video generation.
- @gpuai/sdk on npm — the published package: release history, metadata, and the full per-method reference in the README.
Snippets on this page were run-verified against the live API.