Backend SDK
@dataira/node is an optional server-only wrapper around the REST API. Keep its
API key in a secret manager; never import this package into a browser bundle.
The package is public on npm.
The live demo uses this same server-to-browser token boundary with a dedicated demo Project, Environment, and datasource.
npm install @dataira/node
Mint an end-user token
import { Dataira } from "@dataira/node";
const dataira = new Dataira({
apiKey: process.env.DATAIRA_API_KEY!,
baseUrl: "https://api.dataira.ai",
});
const { token } = await dataira.createToken({
endUserId: user.id,
endUserOrgId: user.organizationId,
datasourceId: "ds_123",
scopeColumn: "account_id",
scopeValue: user.accountId,
});
Your runtime API key already fixes the Partner organization, Project, and Environment.
Dataira derives those values from the key; the browser or request body cannot
override them. The token adds the end-user organization, end user, datasource,
and row-level data scope. If your product has no organization model, omit
endUserOrgId; it defaults to endUserId.
The first valid mint registers the user beneath that Partner and Environment. Later attempts to silently move the same Environment user to a different end-user organization are rejected. This prevents a key or token from reading assets outside its full identity scope.
Showing or hiding SQL evidence
allowSqlEvidence is a boolean field on createToken. It controls what the
end user sees in chat answers, conversation titles, and asset names.
Default: true. Omit the field and evidence is visible. Nothing to
configure.
Two conditions decide the outcome. The table is exhaustive:
Key has embed.sql_evidence.read | allowSqlEvidence at mint | Session shows |
|---|---|---|
| yes (runtime keys: yes by default) | omitted or true | Full answer: assistant analysis, generated SQL, real conversation titles, real asset names |
| yes (runtime keys: yes by default) | false | Neutral "analysis complete" placeholder instead of answer text; SQL hidden; asset names neutralized |
| no | any value | Same as the row above. The permission is the hard gate: no permission, no evidence, regardless of the flag |
Exact behavior when evidence is hidden:
- Chat answers: the user sees
"Analysis complete. Model-authored text and restricted query evidence are hidden by this embed session's evidence policy."— the analysis itself is withheld, not just the SQL. - Conversation titles: replaced by a neutral name.
- Metric and dashboard names: replaced by neutral names.
Use false only when your end users must never see SQL or model text, for
example a non-technical audience. If you are building an analytics tool where
users want to verify the SQL, leave the default.
const { token } = await dataira.createToken({
endUserId: user.id,
datasourceId: "ds_123",
scopeColumn: "account_id",
scopeValue: user.accountId,
allowSqlEvidence: false, // hide SQL and model-authored text for this session
});
Note for integration agents: if your users report seeing the "Analysis
complete … hidden by this embed session's evidence policy" message, the cause
is one of: (1) the minting key lacks embed.sql_evidence.read — recreate the
key with runtime permissions, or (2) your mint call passes
allowSqlEvidence: false — remove it. Since the default flip (2026-08-22),
omitting the field shows evidence.
Use dataira.dataPolicies.list/create/update for typed, generation-CAS policy
management. Bind a trusted server identity with dataira.setUserAccess({ endUserOrgId, endUserId, datasourceIds, policyId, roles, attributes }). Policy
documents and role/attribute bindings stay server-side; never recreate them in
browser code.
Public SDK functions and JSON use camelCase. Database columns and JWT claims
use snake_case; HTTP paths and package/file names use kebab-case.
Provision Projects and Environments
Use the tenant-level management credential from the Partner portal for this section. It may provision scopes and runtime keys, but it cannot mint end-user tokens itself.
const project = await dataira.projects.create("Acme Analytics");
const production = project.environments[0]; // created automatically
const staging = await dataira.projects.createEnvironment(project.id, {
name: "Staging",
slug: "staging",
});
Environments are optional beyond production. Use them when credentials,
access policy, or end-user assets must be isolated between deployments.
Create an environment-scoped API key
const created = await dataira.apiKeys.create({
name: "Acme production backend",
projectId: project.id,
environmentId: production.id,
});
storeSecret(created.token); // returned once
Both IDs are required and the Environment must belong to the Project. List and
revoke keys with dataira.apiKeys.list() and dataira.apiKeys.revoke(id).
Construct the token-minting Dataira client with created.token; that key is
then fixed to the selected Project and Environment.
Backends in other languages can call the same /api/v1/embed/* endpoints
directly; no Dataira backend SDK or Dataira-hosted user database is required.
Choose an API integration track
| Track | Identity and transport | Status |
|---|---|---|
| Service credential | Dataira stores a least-privilege API token; user scope comes from a governed server policy | Current OpenAPI preview |
| Delegated identity | Allowlisted partner JWT, or trusted assertion exchanged for a short-lived upstream token | Specified, later |
| GraphQL | Persisted operations with field/depth/cost limits; reuses governed identity | Specified, later; not an auth mode |
Never forward a browser session token as an upstream credential. The later JWT profile pins issuer, audience, algorithms, JWKS, claims, rotation, and revocation. The later delegated exchange keeps both assertions server-to-server.
Add a governed OpenAPI source
The public preview is spec-driven. Dataira fetches the same-origin JSON or YAML spec, resolves local references, compiles only your selected operations, pins the public addresses, and stores upstream headers encrypted. Check capabilities instead of assuming the environment is enabled.
const capabilities = await dataira.sourceConnectors.capabilities();
if (!capabilities.openapi.configuration || !capabilities.openapi.execution ||
!capabilities.openapi.canonicalSpec || capabilities.openapi.egress !== "private_pinned_ip") {
throw new Error("OpenAPI is unavailable");
}
await dataira.sourceConnectors.preflightOpenApi({
origin: "https://billing.example.com",
specUrl: "https://billing.example.com/openapi.json",
});
const source = await dataira.sourceConnectors.createOpenApi({
name: "Partner billing",
origin: "https://billing.example.com",
specUrl: "https://billing.example.com/openapi.json",
headers: { Authorization: `Bearer ${process.env.BILLING_READ_TOKEN!}` },
timeoutMs: 3000,
maxRows: 100,
maxBytes: 250000,
selectedOperations: [{
operationId: "listInvoices",
policyTables: ["invoices"],
parameters: [{ name: "account_id", location: "query", source: "policy",
key: "invoices.account_id", required: true, valueType: "string" }],
kind: "query", sideEffect: "none", mode: "sync", responseShape: "rows",
idempotency: "not_applicable", evidenceFields: ["invoice_id"],
responseFields: ["invoice_id", "amount", "currency", "issued_at"],
}],
}, { idempotencyKey: crypto.randomUUID() });
OpenAPI v2 accepts reviewed GET and POST operations declared as synchronous,
side-effect-free queries or computations. It records immutable source/spec
revisions and rejects remote references, unsafe destinations, redirects, and
contract drift. async can be described but is rejected by the current runtime.
Author and execute an Analytical Pack
Construct dataira.analyticalPacks({ projectId, environmentId }) with a
management key. Create an empty draft, resolve a preset with listPresets(),
import its exact digest, and call analyzeOpenApi() with the registered source's
exact generation, spec revision, and reviewed operation IDs. JSON/YAML,
structured Markdown, and agent proposals are bounded untrusted inputs. Preview
diagnostics and conflicts before validate(), submitReview(), and publish().
No import publishes automatically and no conflict uses silent last-write-wins.
Mutations require an idempotency key and revision CAS; publish and rollback also
require the active generation returned by getActive(). The same published
context is used by embed, SDK, REST, and MCP. Follow the complete, reproducible
FretGuard OpenAPI pilot.
Execute a published operation with dataira.analyticalRuntime.execute. This
method requires the short-lived end-user access token, an idempotency key, and
source.datasourceAuthorizationVersion returned by sourceConnectors.list()
or create/update. It returns the normalized
result and persisted execution receipt; it never accepts a management key as a
substitute for end-user identity.
Publication currently evaluates structure, selected operations, side effects, and output fields after exact source-contract validation. It does not call the partner API. A safe server-owned principal and policy for post-publish live conformance remain a product decision. Packages are not public, capabilities are not promoted, and this documentation does not imply a production deploy.
Run pnpm --filter @dataira/node example:conformance before launch. Replace the
example adapters with trusted SQL and OpenAPI callbacks for the same two test
users. The runner proves own-marker visibility, cross-scope override denial,
revocation, and continuity for the unaffected peer.