Dalea SDK

One public API, two lockstep SDKs — coverage, auth, and core concepts.

The Dalea SDK is one public API contract shipped as two official clients — @dalea/sdk (TypeScript/JavaScript) and dalea (Python). Both are generated from the same public OpenAPI subset, so they stay in lockstep: the same operations, the same request/response shapes, mirrored method names (listTables on client.data.environments in TS is list_tables in Python).

This page covers the concepts shared by both SDKs. For runnable, per-language code, go straight to the language pages — and every operation in the API reference carries a ready-to-copy SDK example in both languages.

What the SDK covers

The SDK exposes the public, programmatically-accessible surface of the platform — five domains:

client.data
The data platform: environments, tables, columns, objects, the query engine, saved queries, result batches, schema validation, naming schemes, and import mappings.
client.documents
Document metadata (list, create, get, update) plus the markdown round-trip — read a document as markdown, append/insert/update/replace blocks.
client.inventory
Lab inventory: item types & lots, the container hierarchy, placements (check-in/out, move), a read-only item query, consumption & quantity adjustment, and audit trails. Reads plus the operational writes instrument integrations drive. Item types are data tables, so their schema is managed in the environment designer, not through this client.
client.search
Unified search across documents, files, data objects, and result schemas — filterable by type, environment, project, table(s), author, and date, with offset pagination.
client.storage
Files: uploads (multipart & base64), metadata, short-lived presigned download URLs, and storage-usage breakdowns.

Entity lifecycle is reversible, never hard-deleted. The data domain carries explicit archive / restore pairs: environments, tables, columns, objects, result batches and import mappings. Documents, files and inventory records expose no delete at all. The one exception is documents.markdown.deleteBlocks / delete_blocks, which permanently removes blocks from a document body and requires an audit reason.

Public by design

The public surface deliberately excludes entity deletion, the AI suite, org/workspace settings, and first-party surfaces like notifications and the activity feed. The platform rejects those for API-key / OAuth callers with 403 ENDPOINT_NOT_PUBLIC. See Authentication.

Install

npm install @dalea/sdk

@dalea/sdk runs in Node ≥ 20, browsers, and edge runtimes (ESM + CJS, zero runtime dependencies). dalea needs Python 3.11+ and ships sync + async clients over a pooled httpx transport.

Authentication model

Both SDKs resolve auth the same way: an explicit credential → an explicit API key → (TS only) the session cookie → the DALEA_API_KEY environment variable. In a server script, set DALEA_API_KEY and construct a bare client — it just works.

ApiKeyCredential
A workspace-scoped dalea_… key (Settings → Developer → API Keys). The default for first-party scripts and backends.
OAuthPkceCredential
Third-party apps acting on behalf of a user — OAuth 2.1 + PKCE, with automatic token refresh on 401.
OAuthClientCredentialsCredential
Machine-to-machine — the client-credentials grant for services acting as themselves.
SessionCookieCredential (TS only)
First-party browser apps, same-origin — reuses the logged-in session cookie.
Keep keys server-side

An API key is a secret — use it from server code, never a browser bundle. In a first-party browser app, use the session cookie instead.

See Authentication for obtaining each credential, and the language pages for the construction code.

Workspace context

Every call resolves to a workspace. API keys and OAuth credentials are bound to their workspace when created, so those callers need no extra scoping — a bare client just works. For credentials that don't pin a workspace (chiefly the first-party session cookie), the client sends an X-Workspace header: set a default at construction, change it later (setWorkspace / set_workspace), or override it per call — the per-call value always wins.

Pagination

List methods return one page, keyed by the resource name (for example { environments: [...] } or { objects: [...], total, limit, offset }).

Some listing surfaces also have an auto-paging companion that walks every item across pages, so you never manage cursors or offsets yourself: an async iterator in TypeScript, a generator in Python (sync on DaleaClient, async on AsyncDaleaClient).

  • TypeScript: documents.iterate, storage.files.iterate, data.savedQueries.iterate, data.tables.iterateObjects, data.tables.iterateArchivedObjects, data.tables.searchObjectsAll, and search.searchAll.
  • Python: data.saved_queries.iterate, data.tables.iterate_objects, data.tables.iterate_archived_objects, data.tables.search_objects_all, and search.search_all. Documents and files are cursor-paged by hand here: pass the nextCursor you got back as cursor.

Everything else returns one page at a time.

Retries and errors

Non-2xx responses map to a typed error hierarchy (DaleaError and subclasses like DaleaNotFoundError, DaleaValidationError, DaleaRateLimitError). Throttling (429) and transient 503s are retried automatically with exponential backoff + jitter honoring Retry-After, but the two differ on writes. A 429 is rejected before the handler runs, so replaying is safe and any method is retried, writes included, unless you set retryWrites / retry_writes to false. A 503 can be thrown from inside a handler after a write committed, so it is replayed for idempotent GETs only, never for a write, whatever retryWrites says. A rate-limit error surfaces only once retries are exhausted; retry counts and delays are tunable per client.

Contract parity

Both SDKs, and the API reference, are generated from the same public OpenAPI document, and CI fails if either client drifts from the contract. That has a practical upside: browse any operation in the reference, and copy its @dalea/sdk or dalea snippet straight into your code.

Next