LizzyDocs
Docs navigation Quickstart

Quickstart · About 15 minutes

Quickstart: create a Distill loop

Configure a test token, verify its workspace and scopes, create a Distill loop, and handle an interrupted request without creating duplicates.

Set up the example environment

You need a Lizzy workspace, an owner or admin who can create a test token, and a server-side environment for your integration. The examples use cURL, Python 3 withrequests, or Node.js 18 or newer. Start with a test token carryingdistill:read and distill:write.

bashlocal shell
mkdir lizzy-first-integration
cd lizzy-first-integration


export LIZZY_API_BASE="https://lizzy.albinilabs.com/v1"
export LIZZY_API_TOKEN="<lizzy-test-token>"


# Only needed for the Python examples
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install requests

The example value is intentionally not a usable secret. Create the real token in the Lizzy token dashboard, copy it once, then inject it through your deployment platform’s secret store.

Verify the token

GET /v1/whoami is the fastest way to prove four assumptions: the token is valid, it belongs to the intended workspace, it is in test mode, and it has the scopes your code expects. Run this check during setup and include it in an operator diagnostic, but do not call it on every application request.

cURLexample
curl --fail-with-body "$LIZZY_API_BASE/whoami" \
  -H "Authorization: Bearer $LIZZY_API_TOKEN"

A successful token-authenticated response has this shape:

jsonexample 200 response
{
  "object": "whoami",
  "workspace": {
    "id": "ws_01K2ZXQ8M4Y7V6R5T3S9N2P1A0",
    "name": "Acme AI",
    "plan": "prepaid"
  },
  "credential": {
    "type": "api_token",
    "id": "tok_01K2ZXQ8M4Y7V6R5T3S9N2P1B1",
    "name": "developer-quickstart",
    "environment": "test",
    "scopes": ["distill:read", "distill:write"]
  },
  "livemode": false,
  "api_version": "2026-07-01"
}

Create a Distill loop

A loop owns the intent and navigation context for one experiment pipeline. Sources, datasets, runs, models, reports, and deployments can be traced back to it. The loop itself is workspace-scoped; its child resources are separated by test or live mode.

  1. 1

    Choose a stable idempotency key

    Derive it from your own operation ID, such asquickstart:loop:support-quality:v1. Reuse the exact key and exact body after a timeout. Do not generate a new key for every retry.

  2. 2

    Create the loop

    Send a descriptive goal. Lizzy generates the slug when you omit it and returns HTTP 201 with the new loop.

  3. 3

    Persist response.id

    The identifier is id, not loop_id. Later request bodies use that value in a loop field when the operation supports loop scoping.

cURLexample
curl --fail-with-body -X POST "$LIZZY_API_BASE/distill/loops" \
  -H "Authorization: Bearer $LIZZY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: quickstart:loop:support-quality:v1" \
  -d '{"name":"Support quality","description":"Reduce inference cost while preserving resolution quality"}'
jsonexample 201 response
{
  "id": "dlp_01K2ZXQ8M4Y7V6R5T3S9N2P1D3",
  "object": "distill_loop",
  "name": "Support quality",
  "slug": "support-quality",
  "description": "Reduce inference cost while preserving resolution quality",
  "status": "active",
  "counts": {
    "sources": 0,
    "datasets": 0,
    "runs": 0,
    "live_deployments": 0,
    "captured_calls": 0
  },
  "created_at": "2026-08-15T09:30:00Z",
  "updated_at": "2026-08-15T09:30:00Z"
}
GET/v1/distill/loops/{loop_id}

Reconcile your local record at any time. A loop can be archived and restored; deleting it does not erase its experiment artifacts.

Run the funded sandbox

The Distill sandbox is a workspace-scoped demonstration resource. It pulls a public tool-use corpus, replays examples through a platform-funded teacher within a hard spend cap, and captures the results as ordinary test-mode artifacts. It does not attach those artifacts to the loop you just created. Use it to learn states and recovery, not as your production ingest path.

  1. 1
    empty

    No sandbox work exists yet.

  2. 2
    pulling

    Lizzy is fetching and normalizing the public corpus.

  3. 3
    replaying

    Teacher calls are running and progress is saved after each batch.

  4. 4
    ready or capped

    Replay reached the available rows, call target, or spend cap.

  5. 5
    dataset version

    Freeze captured calls, then poll the returned dsv_ resource to ready or failed.

bashadvance, inspect, and freeze
# POST returns 202. replay_batch selects a replay batch size, from 1 to 500.
curl --fail-with-body -X POST "$LIZZY_API_BASE/distill/sandbox" \
  -H "Authorization: Bearer $LIZZY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"replay_batch":25}'


# Poll at a fixed interval. Stop on ready, capped, paused, or error.
curl --fail-with-body "$LIZZY_API_BASE/distill/sandbox" \
  -H "Authorization: Bearer $LIZZY_API_TOKEN"


# Once calls_sent is greater than zero, freeze them into an immutable version.
curl --fail-with-body -X POST "$LIZZY_API_BASE/distill/sandbox/dataset" \
  -H "Authorization: Bearer $LIZZY_API_TOKEN"
jsonexample sandbox state
{
  "object": "distill_sandbox",
  "status": "replaying",
  "corpus": { "rows_pulled": 10000, "rows_target": 10000 },
  "replay": {
    "calls_sent": 125,
    "calls_target": 10000,
    "teacher_spend_usd": 1.3842,
    "spend_cap_usd": 20.0
  },
  "dataset": null,
  "dataset_version": null,
  "latest_run": null,
  "latest_report": null,
  "error": null
}

Retry requests without duplicating work

Treat the HTTP outcome, response body, diagnostic request ID, idempotency key, and any returned resource ID as one operation record. That record lets a developer explain what happened before changing anything.

  1. 1
    A read failed

    Retry the same GET with exponential backoff and a deadline. Reads do not create resources.

  2. 2
    A create timed out

    Retry the exact body with the original Idempotency-Key, then persist the returned ID.

  3. 3
    An async watch timed out

    GET the existing resource ID. Do not POST a replacement just because your local wait ended.

  4. 4
    A terminal state failed

    Inspect the resource error, fix the named prerequisite, and use the operation-specific retry path.

jsonLizzy control-plane error
{
  "error": {
    "type": "permission_error",
    "code": "insufficient_scope",
    "message": "This token is missing the required scope: distill:write.",
    "param": null,
    "request_id": "req_0123456789abcdefabcd"
  }
}

Branch on error.code, not the prose message. For authentication failures, verify the token and scopes with /v1/whoami. For sandboxerror states, inspect error.code: corpus pull, teacher replay, capture, teacher usage, and upstream teacher failures need different fixes. Continue with the authentication, capture, dataset, and error guides once this quickstart works.