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.