authentication.md

Authentication & scopes

The SDK authenticates with a Maritime API key (mk_…). It lives on your server and never touches a browser.

Get a key

Mint one from the dashboard (Settings → API keys) or with maritime keys create. Set it as MARITIME_API_KEY and both SDKs pick it up automatically.

Screenshot: A default key is full-access; open Advanced to scope it down.

Scopes

Every key carries scopes. Hand a subsystem the narrowest key it needs. A leaked key can then only do what its scope allows. manage is a wildcard.

Scope Grants
provision create agents
deploy start / stop / restart / sleep / chat
secrets read / write env vars
manage everything, incl. delete + key management (wildcard)
computers the Computers product (MCP and /api/v1/computers); a key with only this scope reaches nothing else, and manage or full access reach Computers too
sandboxes Sandboxes (create, run, snapshots, secrets, sandbox webhooks); manage reaches them too. Starting a swarm needs provision

Mint a scoped key

A background worker that only chats to existing agents needs deploy, not provision, secrets, or manage. Minting keys itself requires a manage key.

Without scopes a key gets provision, deploy, secrets and manage; computers and sandboxes are never added for you (manage already covers them). Pass projectId (project_id in Python) to tie a key to one project: it then works only on that project's front door and usage routes and is refused everywhere else. Use it for a per-tenant or partner-facing service.

TypeScript

const worker = await maritime.keys.create({
  name: 'chat-worker',
  scopes: ['deploy'],   // chat/start/stop only
})
// worker.rawKey is shown once. Hand it to the worker as MARITIME_API_KEY.

const tenant = await maritime.keys.create({ name: 'tenant-a', projectId: agent.projectId })

Python

worker = client.keys.create("chat-worker", scopes=["deploy"])
# worker["raw_key"] is shown once. Hand it to the worker as MARITIME_API_KEY.

tenant = client.keys.create("tenant-a", project_id=agent["projectId"])

Per-sandbox keys

To let code inside or next to one sandbox drive only that sandbox, mint a per-sandbox key (msk_…) with keys.create({ sandbox }). It lasts one day by default (60 seconds to 30 days) and its secret is returned once.

const key = await maritime.keys.create({ sandbox: sandbox.id, ttlSeconds: 3600 })
// key.secret is shown once.
key = client.keys.create(sandbox=sandbox.id, ttl_seconds=3600)
# key.secret is shown once.

Note: A key sent as a session token (dashboard) and an admin key are always full-access. Scope enforcement applies to user mk_ keys, so restricted keys are genuinely restricted.