Skip to main content
This walks through installing spine-sdk, creating a run, waiting for it to finish, and downloading the generated artifacts. For a broader conceptual tour of the API, see the API quickstart.

1. Install

npm install spine-sdk
Requires Node.js 18 or newer. Also works in modern browsers, Deno, Bun, and Cloudflare Workers without any extra configuration.

2. Get an API key

Create a key in the developer portal. You get $5 of free credits immediately — enough for several test runs end-to-end. Keys look like sk_spine_... and are shown only once. Export it into your environment so the SDK can pick it up:
export SPINE_API_KEY=sk_spine_...
See Authentication for key rotation, staging overrides, and tracing hooks.

3. Run your first request

import { writeFile } from 'node:fs/promises';
import { Spine, downloadArtifact } from 'spine-sdk';

const client = new Spine({ apiKey: process.env.SPINE_API_KEY! });

const run = await client.runs.create({
  prompt: 'Summarise the Q4 2025 AI chip market in three paragraphs.',
  template: 'memo',
});
console.log('Run started:', run.run_id);

const terminal = await client.runs.waitForCompletion(run.run_id);

if (terminal.status !== 'failed') {
  console.log(terminal.result.final_output);
  for (const artifact of terminal.result.artifacts) {
    const blob = await downloadArtifact(artifact);
    await writeFile(artifact.name, Buffer.from(await blob.arrayBuffer()));
  }
}

What happens

  1. runs.create submits the prompt and returns a CreatedRun handle immediately.
  2. waitForCompletion polls GET /v1/run/{run_id} every 5 seconds until the run reaches a terminal state.
  3. On success, terminal.result.final_output holds the synthesized markdown and terminal.result.artifacts lists downloadable files (docx, xlsx, pptx, html, png — depending on the template).
See Runs and polling for all the options.

4. Upload files with a run

import { readFile } from 'node:fs/promises';

const data = await readFile('./market_data.pdf');
const run = await client.runs.create({
  prompt: 'Read the attached files and produce a 1-page summary.',
  template: 'report',
  files: [
    { data: new Uint8Array(data), filename: 'market_data.pdf', contentType: 'application/pdf' },
    { data: new TextEncoder().encode('# Supplementary context\n...'), filename: 'inline.md' },
  ],
});
Accepts File, Blob, ArrayBuffer, Uint8Array, or { data, filename, contentType } records. Supported types are documented on File uploads.

5. Handle errors

Every failure is a subclass of SpineError. Branch on the specific types when you need to:
import { Spine, SpineBadRequestError, SpineAuthError } from 'spine-sdk';

try {
  const client = new Spine({ apiKey: process.env.SPINE_API_KEY! });
  await client.runs.create({ prompt: '', template: 'bogus' as 'memo' });
} catch (err) {
  if (err instanceof SpineBadRequestError) {
    console.error('Rejected:', err.message);
  } else if (err instanceof SpineAuthError) {
    console.error('Check your SPINE_API_KEY');
  } else {
    throw err;
  }
}
See Errors and retries for the full hierarchy and how transient failures are retried automatically.

Next steps

Runs and polling

Stream progress, tune poll intervals, use the low-level runs.retrieve.

Canvas introspection

Inspect the block graph and task tree a run produced.