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.
@dalea/sdk by example — browser, Node & edge.
dalea by example — sync + async, backend/agents.
Every public operation, with SDK code samples.
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.
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.
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, andsearch.searchAll. - Python:
data.saved_queries.iterate,data.tables.iterate_objects,data.tables.iterate_archived_objects,data.tables.search_objects_all, andsearch.search_all. Documents and files are cursor-paged by hand here: pass thenextCursoryou got back ascursor.
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.