Klineo/Docs
Open app ↗

Get started

Quickstart

Make your first authorized request, then optionally persist a deterministic sandbox study. This walkthrough works with either SDK and requires an API environment and organization access supplied by your administrator.

Before you begin#

Install your chosen SDK using installation. Configure KLINEO_API_BASE_URL, KLINEO_ORGANIZATION_ID, and KLINEO_ACCESS_TOKEN in the process environment. Use the full v2 API root as the base URL, ending in /api/liquidity-studio/v2.

For the first request, your API key or OAuth token needs scores:read. For the optional sandbox, it also needs studies:write to create a study and studies:read to retrieve it. The credential owner must remain an authorized member of the organization. Study creation also checks the owner's evidence-creation role.

Keep credentials in the server process or secret manager. These examples print records and diagnostic codes, and never print the credential.

1. Read one page of market-quality scores#

TypeScript#

Create quickstart.mjs in an ESM application with the SDK installed:

js
import { LiquidityOsClient, LiquidityOsApiError } from '@klineo/liquidity-os-sdk';

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} before running this example.`);
  return value;
}

const client = new LiquidityOsClient({
  baseUrl: required('KLINEO_API_BASE_URL'),
  organizationId: required('KLINEO_ORGANIZATION_ID'),
  accessToken: required('KLINEO_ACCESS_TOKEN'),
});

try {
  const page = await client.listScores({ query: { limit: 10 } });
  for (const record of page.data) {
    console.log(record.id, record.resourceVersion, record.payload);
  }
  console.log({ count: page.meta.count, hasMore: page.meta.hasMore });
} catch (error) {
  if (error instanceof LiquidityOsApiError) {
    console.error({ status: error.status, code: error.code, correlationId: error.correlationId });
  } else {
    console.error(error instanceof Error ? error.message : 'Request failed.');
  }
  process.exitCode = 1;
}

Run it:

bash
node quickstart.mjs

Python#

Create quickstart.py:

python
import os

from klineo_liquidity_os import LiquidityOsApiError, LiquidityOsClient

client = LiquidityOsClient(
    base_url=os.environ["KLINEO_API_BASE_URL"],
    organization_id=os.environ["KLINEO_ORGANIZATION_ID"],
    access_token=os.environ["KLINEO_ACCESS_TOKEN"],
)

try:
    page = client.list_scores(query={"limit": 10})
    for record in page["data"]:
        print(record["id"], record["resourceVersion"], record["payload"])
    print({"count": page["meta"]["count"], "hasMore": page["meta"]["hasMore"]})
except LiquidityOsApiError as error:
    print({"status": error.status, "code": error.code, "correlationId": error.correlation_id})
    raise SystemExit(1) from error

Run it in your activated Python environment:

bash
python quickstart.py

Understand the response#

GET /scores returns a data array of versioned records and a meta pagination object. An empty data array is successful: it means no records were returned for this workspace.

Each record includes its organization, ID, payload, status, version, resourceVersion, artifactHash, and evidence hashes. Keep those version and evidence identifiers if your integration uses the result in a later review.

If meta.hasMore is true, request the next page by passing the returned meta.nextCursor as query.cursor. Treat a cursor as opaque and keep it with the same collection and organization. Collection limits range from 1 to 100.

2. Prepare a sandbox study#

The sandbox calls POST /sandbox/studies with an inline issuer intent. It does not require a funded vault. It persists a completed simulation study and grants no custody, signing, or execution authority.

Save the following as sandbox-study.json beside your example. The amounts are illustrative atomic quote units, not whole-token balances. Every amount uses the same quote scale in this example. When using real inputs, choose and retain the correct quote-asset decimals. Pips use a denominator of 1,000,000: 500000 means 50%, and 10000 means 1%.

json
{
  "intent": {
    "name": "Developer sandbox liquidity intent",
    "quoteSymbol": "USDT",
    "targetTradeSizeQuote": "100000",
    "maximumSlippagePips": 50000,
    "executableDepthQuote": "1000000",
    "executableDepthBandPips": 100000,
    "treasuryReservePips": 200000,
    "capitalCeilingQuote": "5000000",
    "maximumDailyTurnoverPips": 120000,
    "acceptableVolatilityPips": 80000,
    "duration": { "kind": "ROLLING", "days": 90 },
    "prohibitedBehaviors": ["arbitrary calldata"]
  },
  "seed": "klineo-developer-quickstart-v1",
  "pathCount": 2000,
  "stepCount": 6,
  "startingPortfolioQuote": "5000000",
  "startingDepthQuote": "3000000",
  "startingInventoryPips": 500000,
  "scenario": {
    "id": "sandbox-bear-one",
    "name": "Bear and withdrawal scenario",
    "kind": "COMBINED",
    "driftPipsPerStep": -2000,
    "volatilityPipsPerStep": 30000,
    "liquidityWithdrawalPips": 100000,
    "oneSidedFlowPips": 50000,
    "gasIncreasePips": 20000,
    "unlocks": []
  },
  "reason": "Run a deterministic developer sandbox study."
}

Sandbox studies accept exactly 2,000 paths and 1 to 365 steps. The fixed seed makes the simulation engine's computation reproducible for the same inputs and engine version. Generated record IDs and timestamps are not part of that computation.

3. Submit and retrieve the study#

Choose an idempotency key once for this intended submission and save it as KLINEO_IDEMPOTENCY_KEY in your process environment. Reuse that value with the same body when retrying an uncertain response. Choose a new key for a new intended study. Do not automatically create a new key on every retry.

TypeScript#

Create sandbox.mjs:

js
import { readFile } from 'node:fs/promises';
import { LiquidityOsClient } from '@klineo/liquidity-os-sdk';

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} before running this example.`);
  return value;
}

const client = new LiquidityOsClient({
  baseUrl: required('KLINEO_API_BASE_URL'),
  organizationId: required('KLINEO_ORGANIZATION_ID'),
  accessToken: required('KLINEO_ACCESS_TOKEN'),
});

const body = JSON.parse(await readFile('sandbox-study.json', 'utf8'));
const response = await client.runNonCustodialSandboxStudy({
  body,
  idempotencyKey: required('KLINEO_IDEMPOTENCY_KEY'),
});
const study = response.data.study;
console.log({
  id: study.id,
  status: study.status,
  artifactHash: study.artifactHash,
  resourceVersion: study.resourceVersion,
  sourceLineage: study.payload.sourceLineage,
  executionAuthorityGranted: response.data.executionAuthorityGranted,
});

const saved = await client.getStudies({ path: { id: study.id } });
console.log(saved.data.payload.recommendedVariant, saved.data.payload.warnings);
bash
node sandbox.mjs

Python#

Create sandbox.py:

python
import json
import os

from klineo_liquidity_os import LiquidityOsClient

client = LiquidityOsClient(
    base_url=os.environ["KLINEO_API_BASE_URL"],
    organization_id=os.environ["KLINEO_ORGANIZATION_ID"],
    access_token=os.environ["KLINEO_ACCESS_TOKEN"],
)
with open("sandbox-study.json", encoding="utf-8") as source:
    body = json.load(source)

response = client.run_non_custodial_sandbox_study(
    body=body,
    idempotency_key=os.environ["KLINEO_IDEMPOTENCY_KEY"],
)
study = response["data"]["study"]
print({
    "id": study["id"],
    "status": study["status"],
    "artifactHash": study["artifactHash"],
    "resourceVersion": study["resourceVersion"],
    "sourceLineage": study["payload"]["sourceLineage"],
    "executionAuthorityGranted": response["data"]["executionAuthorityGranted"],
})

saved = client.get_studies(path={"id": study["id"]})
print(saved["data"]["payload"]["recommendedVariant"], saved["data"]["payload"]["warnings"])
bash
python sandbox.py

The sandbox response contains sandbox: true, custodyAuthorityGranted: false, signingAuthorityGranted: false, executionAuthorityGranted: false, and networkCodeExecuted: false. The saved study has SANDBOX source lineage and INELIGIBLE_SANDBOX publication eligibility. A sandbox result is modeled evidence; it cannot be treated as an execution receipt or admitted production strategy evidence.

If a request fails#

Result Check
401 Credential validity, expiry, rotation, and organization binding.
403 The exact service scope and the credential owner's workspace membership and role.
400 Request field names, atomic string amounts, integer pips, and scenario constraints.
409 Idempotency reuse with changed inputs or another operation-specific conflict.
429 Rate-limit guidance and Retry-After; retain the same idempotency key for the same mutation.
503 An unavailable dependency or environment capability; check the error code before retrying.

Use the structured error code to distinguish these cases and retain its correlation ID for support. See errors and recovery for the full envelope and idempotency before adding automatic mutation retries.

Continue with simulation mechanics, your TypeScript or Python SDK guide, and the API reference.