Authentication & API keys
Server-side SDK code authenticates with an API key. The CLI uses a browser-approved member session. Browser code never holds either credential; it uses a short-lived session or token minted by your backend. Every credential resolves to a project and an environment server-side.
API keys
An API key is a long-lived credential that server-side SDK code and automation use to run agents. Each key:
- is scoped to one environment (
development,staging, orproduction) so test and live traffic stay cleanly separated; - carries the platform’s
runtimescapability; - is shown once at creation and stored hashed, so copy it immediately, because it can’t be retrieved again;
- is sent as a bearer token on every request:
Authorization: Bearer <token>.
API-key capability
Public API keys have one capability:
| Capability | Grants |
|---|---|
telemetry:write | Emit telemetry; present on every key. |
runtimes | Read recipes and runtimes, manage experiments, open runners, and drive tasks, files, shares, conversations, events, and metrics within the key’s project and environment. |
telemetry:write is always granted. remotes is not an API-key capability:
it is reserved for the first-party CLI login used by introspection dev.
CLI login
introspection login uses the OAuth device flow and stores a member-bound session at ~/.introspection/credentials.json. The server, not the command line, chooses the granted CLI capabilities: runtimes for platform/operator commands and remotes for introspection dev. The CLI does not accept a capability selector, and applications or API keys cannot request the CLI-only remotes scope.
The CLI refreshes its login transparently and preserves the server-issued scope. See CLI for the login and profile workflow.
Configuring the client
The SDK reads its credentials and target URL from the environment by default. Set INTROSPECTION_TOKEN and the client picks it up:
export INTROSPECTION_TOKEN="ik_..."import { IntrospectionClient } from "@introspection-sdk/introspection-node";
// Reads INTROSPECTION_TOKEN from the environment.
const client = new IntrospectionClient();
// ...or pass the token explicitly.
const explicit = new IntrospectionClient({
token: process.env.INTROSPECTION_TOKEN,
});The base API URL defaults to https://api.introspection.dev. Override it with INTROSPECTION_BASE_API_URL (for example to point at a different deployment).
Environment variables
| Variable | Default | Purpose |
|---|---|---|
INTROSPECTION_TOKEN | None | The SDK API key, sent as Authorization: Bearer <token>. Required for SDK platform calls unless a local development session supplies credentials. |
INTROSPECTION_BASE_API_URL | https://api.introspection.dev | Base URL for the platform API. |
Server & machine auth
A long-lived INTROSPECTION_TOKEN is the simplest credential. For headless or CI callers that shouldn’t ship a static key, authenticate as a confidential service account instead: the SDK mints a short-lived, project-scoped token via the OAuth client_credentials grant and wires it in, so the rest of the flow is unchanged.
import { IntrospectionClient } from "@introspection-sdk/introspection-node";
const client = await IntrospectionClient.fromServiceAccount({
clientId: process.env.INTRO_SA_CLIENT_ID, // confidential client id
clientSecret: process.env.INTRO_SA_CLIENT_SECRET, // kept server-side
projectId: process.env.INTRO_PROJECT_ID, // token is project-scoped
});
const runner = await client.runtimes("support-agent").run();The Python SDK mirrors this with IntrospectionClient.from_service_account(...) (and an awaitable AsyncIntrospectionClient.from_service_account(...) twin). The minted token isn’t auto-refreshed, so re-mint it once it expires.
Brokering a token to the browser
When your server is a token broker for a browser app, mint the token directly so you can also read dp_url, the Data Plane endpoint the platform resolves for the project, and resolve the runtime name to a concrete id server-side. Hand the browser { token, runtimeId, dpUrl } so it connects straight to the Data Plane and never calls the platform API:
import {
IntrospectionClient,
serviceAccountToken,
} from "@introspection-sdk/introspection-node";
const { access_token, dp_url } = await serviceAccountToken({
clientId: process.env.INTRO_SA_CLIENT_ID,
clientSecret: process.env.INTRO_SA_CLIENT_SECRET,
projectId: process.env.INTRO_PROJECT_ID,
});
const client = new IntrospectionClient({ token: access_token });
const runtime = await client.runtimes.resolve("support-agent");
// hand { access_token, runtime.id, dp_url } to the browser clientThe Python equivalents are service_account_token(...) and client.runtimes.resolve(...) (await it on the async client).
Browser apps
Browser code must not carry an API key; anything shipped to the client is public. Instead, client apps use the separate @introspection-sdk/introspection-browser/api package and its IntrospectionApiClient, which authenticates with a cookie session.
The session is issued by a backend token broker: your server holds the API key or service-account secret, exchanges it for a scoped, short-lived browser session, and the browser client rides that session. The long-lived credential never leaves your backend.
import { IntrospectionApiClient } from "@introspection-sdk/introspection-browser/api";
// Authenticates via the cookie session your backend broker established.
const client = new IntrospectionApiClient();Never put an API key in browser code, a mobile app, or anything you ship to an end-user. Use the browser SDK with a backend token broker instead.
Related
- Projects: the workspace a key resolves to.
- Environments: the lane a key is scoped to.
- API Reference: the REST surface keys authenticate against.