Getting started

Your first booking in seven calls.

A walkthrough that takes a brand-new tenant from zero to a confirmed Booking with lifecycle emissions firing — using nothing but curl. The narrative is a salon appointment system, but the same shape applies to any Seldon Offer.

Before you start: You need a tenant. Create one — it takes a couple of minutes — and the steps below run against the production base URL with it.

Prerequisites

  • A tenant id and a bearer token (issued when your sandbox is provisioned).
  • A Git repository LatticeKit can read — HTTPS with a deploy token, or SSH with the public key from your tenant's provisioning email.
  • curl and jq on your machine. That's it.

Every example below assumes:

export LK_BASE="https://api.latticekit.app"
export LK_TOKEN="<your-bearer-token>"

1 — Register your config repo with Radiant

Radiant is where every declarative artifact lives — pricing rules, cancellation policies, message templates. Point it at a Git repository your tenant trusts:

curl -sX POST "$LK_BASE/radiant/v1/repositories" \
  -H "Authorization: Bearer $LK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name":          "main-config",
    "gitUrl":        "https://github.com/your-org/lattice-config.git",
    "defaultBranch": "main"
  }' | jq

You get back a rep… id. Save it; you will point Assets at it next.

2 — Publish a pricing asset

Commit a pricing YAML to your repo at, say, pricing/haircut.yaml, then register it as an Asset and publish a Version:

curl -sX POST "$LK_BASE/radiant/v1/assets" \
  -H "Authorization: Bearer $LK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "repositoryId": "rep01J8K2…",
    "name":         "haircut-pricing",
    "path":         "pricing/haircut.yaml",
    "kind":         "seldon.pricing.v1"
  }' | jq

And an Alias that always points at the current main:

curl -sX POST "$LK_BASE/radiant/v1/aliases" \
  -H "Authorization: Bearer $LK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "assetId":  "asse01J9TQ…",
    "name":     "pricing.haircut.production",
    "channel":  "main"
  }' | jq

3 — Define a physical resource in Trantor

An appointment needs a resource — a styling chair — to be bookable against. Create a ResourceType:

curl -sX POST "$LK_BASE/trantor/v1/resource-types" \
  -H "Authorization: Bearer $LK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name":     "Styling chair",
    "key":      "styling_chair",
    "kind":     "discrete"
  }' | jq

You can add concrete Resources (chair 1, chair 2, …) the same way under /trantor/v1/resources when you need them allocated by name.

4 — Create a Seldon Offer

The Offer is what a customer books. A fixed 60-minute haircut that requires one styling chair, with the pricing alias from step 2 pinned:

curl -sX POST "$LK_BASE/seldon/v1/offers" \
  -H "Authorization: Bearer $LK_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name":          "60-minute haircut",
    "kind":          "appointment",
    "durationShape": { "mode": "fixed", "fixedSec": 3600 },
    "partyMin":      1,
    "partyMax":      1,
    "partyDefault":  1,
    "requirements":  [{ "resourceTypeId": "rty01JAZA…", "count": 1 }],
    "radiantAssetId": "asse01J9TQ…",
    "cancelDeadlineSec": 86400,
    "isActive":      true
  }' | jq

5 — Resolve an Availability projection

Once a TimeScheme is attached to the Offer (handled by the admin UI for now), Availability becomes queryable. Find the Availability for the Offer, then ask it for the next two weeks of slots:

curl -sG "$LK_BASE/seldon/v1/availabilities" \
  -H "Authorization: Bearer $LK_TOKEN" \
  --data-urlencode "offerId=offr01JAZB…" | jq '.items[].id'

curl -sG "$LK_BASE/seldon/v1/availabilities/avlb01JAZC…/slots" \
  -H "Authorization: Bearer $LK_TOKEN" \
  --data-urlencode "from=2026-06-12T00:00:00Z" \
  --data-urlencode "to=2026-06-26T00:00:00Z" | jq

You get back a list of slot instances (si… ids) — that is what the next call references.

6 — Create the Booking

One call. Trantor holds the slot atomically, Terminus checks tier entitlement if a BookingAccessRule applies, the Radiant policy version pins, and the Booking enters confirmed:

curl -sX POST "$LK_BASE/seldon/v1/bookings" \
  -H "Authorization: Bearer $LK_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "offerId":        "offr01JAZB…",
    "availabilityId": "avlb01JAZC…",
    "anchor":         { "slotInstanceId": "si01JAZD…" },
    "partyCount":     1,
    "partyMembers":   [{ "displayName": "Greg O." }],
    "customerContact": { "email": "greg@example.com", "displayName": "Greg O." }
  }' | jq

7 — Watch the lifecycle events fire

From this point on, Seldon's emission pipeline drives the lifecycle. The Booking moves confirmed → checked_in → live → completed automatically as time anchors hit; events fan out to Daneel (which can dispatch through Speaker for a confirmation) and to Palver (which can push them to a live UI). Inspect the Booking at any point:

curl -s "$LK_BASE/seldon/v1/bookings/bk01JAZE…" \
  -H "Authorization: Bearer $LK_TOKEN" | jq '.status'

Where to go next

  • Seldon — the full Offer / Availability / Booking model with all five Availability kinds.
  • Terminus — wire identity, tier groups, and consent so your customers stop being walk-up display names.
  • Speaker — route a Daneel-triggered confirmation through the consent gate to email or SMS.
  • Hober + Payments + Mallow — turn this booking into a paid, ledger-recorded sale at check-in.