# 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](/get-started/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](/developers/errors/) for the full envelope and [idempotency](/developers/idempotency/) before adding automatic mutation retries.

Continue with [simulation mechanics](/mechanics/simulation/), your [TypeScript](/sdks/typescript/) or [Python](/sdks/python/) SDK guide, and the [API reference](/developers/api-overview/).
