CUBSTER Join the waitlist
DOCS / GETTING STARTED

Authentication

Every request resolves to exactly one workspace — you can never read or mutate assets outside the workspace your credential is bound to. There are three ways to authenticate.

Session (first-party)

A Netlify Identity cookie (nf_jwt), used by the first-party dashboard. Sign-in is invite-only — your email has to be on the approved safelist. The first approved login auto-creates your profile and a personal workspace.

import { createCubsterClient } from '@cubster/assets'
// Same-origin dashboard: relative requests ride the session cookie.
const cubster = createCubsterClient({ baseUrl: '' })
API key (programmatic)

Send Authorization: Bearer csk_.... A key is bound to one workspace, which scopes every request it makes, and to the services it was created with. Keys are shown in full exactly once, at creation; only a prefix is shown afterward. Never put a key in client-side code — keep it in an environment variable, server-side only.

const cubster = createCubsterClient({ apiKey: process.env.CUBSTER_API_KEY })
Services

A key is scoped to the services (tools) chosen at creation, on top of its bound workspace. Today's services: assets (uploads, assets, and serve URLs), transcription (audio transcription and stored transcripts), realtime (mint live voice sessions), diagrams (publish and serve agent-authored diagrams), artifacts (validate, publish, and serve agent-composed interactive pages), and charts (preview, publish, and serve data-driven charts). GET /api/v1/me and GET /api/v1/services need no service — any key can call them. Keys created before services shipped were backfilled to the services that existed then (assets, transcription) — realtime, diagrams, artifacts, and charts shipped later, so no existing key gained any of them automatically.

A key used outside its services gets 403 with a body naming the missing service and what the key IS enabled for:

403 response
{
  "error": "This API key is not enabled for the 'transcription' service (enabled: assets). Create a key with that service at app.cubster.dev/account/keys.",
  "service": "transcription",
  "enabled": ["assets"]
}

A key's services and name can be edited any time from its page in the dashboard (app.cubster.dev/account/keys/<id>) — the secret is shown once, at creation, and never again, but the services are not fixed at creation. A key removed from a service gets a 403 naming that service on its next call. Manage keys and see the full service registry at app.cubster.dev/account/keys.

Upload grant (third-party browser upload)

A server holding a key mints a short-lived, single-use grant; a third-party browser then uploads one file directly with only that grant — no key, no cookies exposed to the browser.

// Server (has the key):
const grant = await cubster.uploads.createGrant({ maxSize: 5_000_000, ttlSeconds: 300 })
// Browser (no key):
const anon = createCubsterClient()
const asset = await anon.uploads.uploadWithGrant({ grant, file })
The invite gate

The approved-users safelist is the waitlist: an email with an "invited" status can sign in; anything else gets recorded (status "pending") so it can be invited later. A signed-in-but-not-approved session gets back { isApproved: false, email } from GET /api/v1/me rather than a hard error, so a client can show a "you're on the list" screen.