Login
Free Sign Up
Docs
/

Your First Integration with the Ligantic SDK

This tutorial walks you through your first end-to-end integration with the Ligantic SDK: install the package, authenticate with an API key, list a Space, read a Record, and run a Flow.

By the end you will have a small script that talks to a real Ligantic Space and you will have seen the result-based error model in action.

Prerequisites

  • Node.js 22 or later.
  • A Ligantic API key. You create one in Studio, under your organisation's API keys. Keep it secret — it is the only credential the SDK needs.
  • A Space that already contains at least one Schema with a Record, and one published Flow. If you don't have these yet, create them in Studio first; this tutorial focuses on the SDK.

Step 1: Install the SDK

npm install @ligantic/sdk

Step 2: Create a Client

The Ligantic client is the only thing you need to construct. It takes your API key and (optionally) a base URL.

import { Ligantic } from "@ligantic/sdk";

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

The default base URL is https://ligantic.cloud/api/v1. Override baseUrl only for staging or self-hosted deployments. All constructor options are listed in SDK API Reference — LiganticOptions.

Step 3: Verify Authentication

Call identity.me() to confirm the key is valid. The SDK never throws — it returns a Result, so you check the ok flag. For why, see The Result-Based Error Model.

const me = await client.identity.me();

if (me.ok) {
  console.log("Authenticated as", me.value.id);
} else {
  console.error("Auth failed:", me.error.code, me.error.message);
}

If you see UNAUTHORIZED, the key is invalid or revoked.

Step 4: List Your Spaces

const spaces = await client.spaces.list();

if (spaces.ok) {
  for (const space of spaces.value) {
    console.log(space.id, space.title);
  }
} else {
  console.error(spaces.error.message);
}

Pick one Space and hold onto its id — every Space-scoped call below needs it, passed as spaceId.

Step 5: Read a Record

First list the Schemas in the Space, then list the Records in one of them.

if (!spaces.ok) {
  console.error(spaces.error.message);
  process.exit(1);
}
const spaceId = spaces.value[0]?.id;
if (!spaceId) {
  console.error("No spaces found");
  process.exit(1);
}

const schemas = await client.schemas.list(spaceId);
if (!schemas.ok) {
  console.error(schemas.error.message);
  process.exit(1);
}
const schemaId = schemas.value[0].id;

const records = await client.records.list(spaceId, schemaId, { limit: 5 });
if (!records.ok) {
  console.error(records.error.message);
  process.exit(1);
}
for (const record of records.value.entities) {
  console.log(record.id, record.data);
}

Step 6: Run a Flow

A Flow run is asynchronous. flows.run() returns the run's ID (flowExecutionId) immediately; you then poll the run until it reaches a terminal status.

const flows = await client.flows.list(spaceId);
if (!flows.ok) {
  console.error(flows.error.message);
  process.exit(1);
}

const flowId = flows.value[0].id;

const executed = await client.flows.run(spaceId, flowId, { inputs: {} });
if (!executed.ok) {
  console.error(executed.error.message);
  process.exit(1);
}

const runId = executed.value.flowExecutionId;

// Poll the run once per second, for up to 30 checks.
const terminalStatuses = new Set(["succeeded", "failed", "cancelled"]);
let status: string | undefined;
for (let attempt = 0; attempt < 30; attempt++) {
  const run = await client.flows.getRun(spaceId, flowId, runId);
  if (!run.ok) {
    console.error(run.error.message);
    process.exit(1);
  }
  status = run.value.status;
  if (terminalStatuses.has(status)) break;
  await new Promise((resolve) => setTimeout(resolve, 1000));
}
console.log("status:", status);

The loop stops at a terminal status (succeeded, failed, or cancelled), or after 30 checks, whichever comes first.

For the full polling pattern, see How to Run a Flow from CI.

What You Built

You have:

  • Installed @ligantic/sdk.
  • Authenticated with an API key.
  • Listed Spaces, Schemas, and Records.
  • Ran a Flow and polled its run to a terminal status.

Every call followed the same shape — a Result you check with .ok — and the SDK never threw. That is the whole model.

Related pages