Skip to main content

Quickstart

This guide takes you from an empty project to a running state machine in under five minutes. You will install the SDK, publish a machine definition, create an instance, send events to drive it through its states, and watch it transition live.

1. Prerequisites

You need two things before you write any code:

  • Access to the Orchestate private beta. Request access if you do not have it yet. We will set you up with an org and an API key for this walkthrough.
  • An API key. Create one in the console under Settings → API Keys. The raw key is shown once at creation and never again, so copy it immediately. See Auth & API keys for the full flow.

Note — An Orchestate API key looks like orch_ followed by 48 hex characters. Treat it like a password and keep it out of source control — load it from an environment variable instead.

2. Install the SDK

Add the official TypeScript SDK to your project:

npm install @orchestate/sdk

Or with pnpm:

pnpm add @orchestate/sdk

3. Initialize the client

Create an OrchestateClient with your API key. Read the key from the environment so it never lands in your codebase:

import { OrchestateClient } from '@orchestate/sdk';

const client = new OrchestateClient({
  apiKey: process.env.ORCHESTATE_API_KEY!,
});

The client defaults to the hosted API at https://orchestate.wentzel.ai/api. Pass a baseUrl option if you are pointing at a self-hosted runtime (see Self-hosting).

4. Publish your first machine

A machine is a JSON definition with an initial state and a map of states. Each state lists the events it responds to under on, mapping an event name to a target state. Here is a simple order-flow machine: an order starts pending, can be confirmed or cancelled, then moves on to shipped and finally delivered. The delivered and cancelled states are marked final, which moves the instance to a done status when reached.

const machine = await client.machines.publish({
  slug: 'order-flow',
  name: 'Order Flow',
  definition: {
    initial: 'pending',
    states: {
      pending: {
        on: { CONFIRM: 'confirmed', CANCEL: 'cancelled' },
      },
      confirmed: {
        on: { SHIP: 'shipped' },
      },
      shipped: {
        on: { DELIVER: 'delivered' },
      },
      delivered: { type: 'final' },
      cancelled: { type: 'final' },
    },
  },
});

console.log(machine);
// { id: '...', version: 1 }

The slug must match ^[a-z0-9-]+$ and be 80 characters or fewer. Publishing the same slug again creates a new version — existing instances keep running on the version they were created with. For the complete schema (transition objects, guards, actions, and entry/exit hooks), see Machine definitions.

5. Create an instance

An instance is a live, independent execution of a machine. Create one by referencing the machine slug:

const instance = await client.instances.create({
  machineSlug: 'order-flow',
});

console.log(instance);
// { id: '...', currentState: 'pending', status: 'active', machineVersion: 1, createdAt: '...' }

The new instance starts in the machine's initial state with an active status. You can optionally seed it with a context object — structured data that travels with the instance and can be updated by assign actions during transitions.

6. Send events

Drive the instance forward by sending events. Each event has a type(matching a key under the current state's on map) and an optional payload:

const result = await client.instances.send(instance.id, {
  type: 'CONFIRM',
});

console.log(result);
// { fromState: 'pending', toState: 'confirmed', final: false }

The response tells you exactly what happened: the state you left (fromState), the state you landed in (toState), and whether that state is final. Keep sending events to walk the order through to completion:

await client.instances.send(instance.id, { type: 'SHIP' });
// { fromState: 'confirmed', toState: 'shipped', final: false }

const done = await client.instances.send(instance.id, { type: 'DELIVER' });
// { fromState: 'shipped', toState: 'delivered', final: true }

Note — Sending an event whose type is not handled by the current state, or sending to an instance that is no longer active, returns an error. Reaching a final state (here, delivered) moves the instance to done and no further events are accepted.

7. Watch live state

Every instance has a real-time view. Open it in the console's Live Inspector to watch transitions and context updates stream in over a WebSocket as events arrive — useful while you are building and debugging a flow.

From an authenticated browser session you can also subscribe to the same live stream in code with client.instances.subscribe(...), which invokes a callback on every transition and returns an unsubscribe function. Because the inspector socket is authenticated by the browser session, subscribe is intended for the browser rather than server-to-server use. See SDK reference for details.


Next steps

  • Machine definitions — the full JSON schema for states, transitions, guards, and actions.
  • SDK reference — every method on OrchestateClient, including live subscriptions.
  • HTTP API — the underlying REST endpoints if you prefer to call Orchestate directly.