TypeScript SDK
View as MarkdownThe Simmit TypeScript SDK is the official typed client for the Simmit API. It submits SimulationCraft (SimC) profiles, polls job status, reads results, and verifies webhooks, with generated types for every request and response. It targets Node 20+ and ships zero runtime dependencies.
npm install @simmit/sdkSource and issues live at github.com/voidly-labs/simmit-sdk-typescript. The package is published as @simmit/sdk.
#Authenticate
The client reads your secret key from the SIMMIT_SECRET_KEY environment variable by default. Create a client, then create a new key to get one. The secret key spends credits, so keep it server-side and never ship it to a browser.
import Simmit from '@simmit/sdk'
const client = new Simmit({
secretKey: process.env.SIMMIT_SECRET_KEY
// ^^ This is the default and can be omitted
})#Submit and wait
jobs.createAndWait submits a job and resolves once the sim reaches a terminal state. Reach for it from scripts, bots, and queue workers that can hold a promise open until the sim finishes.
const job = await client.jobs.createAndWait({
build: { channel: 'latest' },
profile: { text: profileText }
})
const result = await client.jobs.getResult(job.id)onCreated fires with the job ID before polling starts; onPoll fires after each status poll, so you can surface progress:
await client.jobs.createAndWait(params, {
onCreated: res => console.log('queued', res.id),
onPoll: status => console.log(status.status, status.progress?.percent)
})#Submit, poll, and read separately
A web app can't hold a promise open across requests. Drive the lifecycle yourself instead: jobs.create returns immediately with a job ID to persist, then poll jobs.getStatus on your own cadence and read the result once the job is terminal.
const { id } = await client.jobs.create({
build: { channel: 'nightly' },
profile: { text: profileText }
})
const status = await client.jobs.getStatus(id)
if (status.status === 'completed') {
const result = await client.jobs.getResult(id)
}jobs.getStatus never throws for a job still in flight, so it is the supported way to drive a custom poll loop. For production web flows, subscribe to a job.terminal webhook rather than polling. See Webhooks.
#Typed errors
Every API error is a subclass of SimmitError with a narrowed code and meta. Branch on the class:
import { InvalidProfileError, InsufficientCreditsError } from '@simmit/sdk'
try {
await client.jobs.create(params)
} catch (err) {
if (err instanceof InvalidProfileError) {
console.error(err.meta.blocked) // the rejected profile lines
} else if (err instanceof InsufficientCreditsError) {
console.error(err.meta?.maxAffordableRuntimeSeconds)
} else {
throw err
}
}jobs.createAndWait also throws JobFailedError, JobCancelledError, and JobTimedOutError for the non-success terminal states, plus JobWaitTimeoutError if the wait deadline passes first. On a wait timeout the job keeps running and billing, so call client.jobs.cancel(id) to stop the spend. The underlying status codes are listed in API Errors.
#Verify webhooks
unwrapWebhook verifies a webhook signature and returns the parsed event. It is standalone, so it needs no client and no secret key, only your webhook signing secret. That keeps it safe to run inside a receiver.
import { unwrapWebhook } from '@simmit/sdk'
const event = await unwrapWebhook(
rawBody, // the raw request body, exactly as received
signatureHeader, // the X-Simmit-Signature header value
process.env.SIMMIT_WEBHOOK_SECRET
)
if (event.payload.status === 'completed') {
// handle the terminal job
}See Webhooks for delivery, retries, and the signature scheme.
#Use it in a web app
The SDK is server-side only. A web flow submits a job on one request, persists the returned id, and reads the result on a later request.
new Simmit() throws when no secret key is set. Frameworks that evaluate route modules at build time, like Next.js, run that code with no environment, so construct the client lazily and read the key at first use:
// lib/simmit.ts
import 'server-only'
import Simmit from '@simmit/sdk'
let client: Simmit | undefined
export function simmit(): Simmit {
return (client ??= new Simmit())
}The Next.js web app example wires this end to end: paste a SimC profile, follow a live status page, and render the headline DPS.