SDK Reference
Complete reference for both Maritime SDKs. New here? Start with the Build on Maritime guide. Methods are shown with their TypeScript names; Python uses the same names in snake_case (setEnv is set_env) with keyword arguments.
| Language | Package | Install |
|---|---|---|
| TypeScript / JS | maritime-sdk | npm install maritime-sdk |
| Python | maritime | pip install maritime |
Both are zero-dependency. Source: github.com/maritime-sh/maritime-sdk.
- 1
provision({ externalId })Creates the customer's agent once - 2
chat(id, message)Wakes it if it is asleep and sends the message - 3
replyComes back to your code
Client
The API key defaults to MARITIME_API_KEY; the base URL to MARITIME_API_URL or api.maritime.sh.
import { Maritime } from 'maritime-sdk'
const maritime = new Maritime({
apiKey: 'mk_...', // or MARITIME_API_KEY
baseUrl: 'https://api.maritime.sh', // or MARITIME_API_URL
timeout: 60_000, // per-request ms
maxRetries: 2, // network + 5xx/429
})A failed request is retried up to maxRetries times (default 2), waiting 0.5 s, then 1 s, doubling up to 8 s, or the server's Retry-After up to 20 s. GET and DELETE, the lifecycle calls (start, stop, sleep, restart, reloadEnv) and chat, which sends an Idempotency-Key, retry on 429, 500, 502, 503, 504, timeouts and network errors. Other writes retry only on 429 and 503, and when the connection was refused or DNS failed, so nothing was sent; a timeout or another 5xx may already have applied the write, so it is thrown.
Agents
Access via maritime.agents (TS) / client.agents (Python).
| Method | Does |
|---|---|
| create(params) | Create an agent and start its deploy. Prefer template: a bare framework yields a broken image. |
| provision({externalId, …}) | Idempotent get-or-create by externalId. The recommended per-customer entry point. |
| get(id) | Fetch one agent. |
| list({externalId?, name?}) | List agents, optionally filtered. |
| chat(id, message, {conversationId?}) | Send a message, wait for the reply. Auto-wakes a sleeping agent. |
| start / stop / sleep / restart(id) | Lifecycle transitions. |
| setEnv(id, key, value, {secret}) | Upsert an env var (secrets encrypted at rest). |
| listEnv(id) / deleteEnv(id, key) | Read / remove env vars. |
| reloadEnv(id) | Push env changes into the running container. |
| resize(id, {memMb?, diskGb?}) | Change RAM or disk; both apply on the next restart. null clears a value back to the base allocation. |
| setVisibility(id, visibility) | 'private' (share-link holders only) or 'public' (anyone with the agent URL; a visit wakes it). public needs a verified account. |
| webhookToken(id) | The agent's invoke token and URL; POST to the URL wakes the agent with a payload. |
| rotateWebhookToken(id) | Replace the invoke token. The old one stops working at once. |
| network(id) / updateNetwork(id, update) / testNetwork(id, destination) | Read or change internet policy, exit and private access; try one TCP connection to host:port from inside the agent. |
| exec(id, command, {timeout?}) | Run a one-shot shell command and wait for it. Wakes a sleeping agent. |
| logs(id, {limit?, level?}) | Recent log entries. |
| delete(id) | Tear down the agent (container + volume + network). |
Files, skills and share links of an agent hang off maritime.agents:
| Method | Does |
|---|---|
| files.list(id, path?) / download(id, path) | Browse the agent's files; download returns bytes. |
| files.upload(id, {content, filename, destDir?}) / write(id, path, content) | Upload bytes or write a text file. |
| files.mkdir(id, path) / move(id, from, to) / delete(id, path) | Create a folder, move or delete a path. |
| skills.list(id) / search(id, q, {limit?}) | The agent's skills (eligible, blocked, unsupported), or search ClawHub. |
| skills.install(id, {slug?, git?, version?, force?, env?}) | Install from ClawHub (slug) or a git repo (git). |
| skills.upload(id, {archive, name?, env?}) | Install a custom skill from a zip or a bare SKILL.md. |
| skills.setEnv(id, env) / setAllowlist(id, allowlist) | Give a skill the env values it waits on; replace the allowlist (null for no limit). |
| skills.remove(id, name) / export(id, name) | Remove a skill, or download it as a .tar.gz. |
| shareLinks.create(id, {ttlSeconds?, endUserExternalId?}) | A link that opens a private agent URL. Default one hour; null lasts until revoked. |
| shareLinks.list(id) / revoke(id, linkId) / revokeForEndUser(id, externalId) | List links, revoke one, or revoke every link bound to an end user. |
create / provision parameters
| Param | Type | Notes |
|---|---|---|
| name | string | Unique per account. Required. |
| template | string | openclaw · zeroclaw · hermes · claude_code · dsh · … (see frameworks) |
| externalId | string | Your own id for this agent. Filterable; idempotency key for provision. |
| instructions | string | Plain-English persona / system prompt. |
| env | {key,value,secret}[] | Seed env vars. Secrets encrypted at rest. |
| idleTtlSeconds | number | Idle seconds before auto-sleep. |
// Idempotent per-customer provisioning (recommended)
const agent = await maritime.agents.provision({
externalId: `customer_${userId}`,
name: `assistant-${userId}`,
template: 'openclaw',
})
const { response } = await maritime.agents.chat(agent.id, 'Hello')
await maritime.agents.setEnv(agent.id, 'STRIPE_KEY', 'sk_live_...', { secret: true })
const { root } = await maritime.agents.files.list(agent.id) // browse / upload / download
await maritime.agents.exec(agent.id, ['ls', '-la', root]) // one-shot shell command
await maritime.agents.sleep(agent.id)
await maritime.agents.delete(agent.id)Exec waits by default. See command execution for detached Python submission, REST retrieval and cancellation, and timeout defaults.
End users
Your own users, keyed by the id you already hold. Access via maritime.endUsers (TS) / client.end_users (Python). See the end users guide.
| Method | Does |
|---|---|
| upsert(externalId, {displayName?, metadata?, tags?}) | Create the end user, or update the fields given. |
| get(externalId) | One end user with its agents. |
| list({status?, tag?, externalIdPrefix?, q?, projectId?, agentId?, sort?, lastActiveBefore?, lastActiveAfter?, cursor?, limit?}) | One page of end users, newest first. Follow nextCursor for more. |
| activity(externalId, {limit?}) | Recent messages with replies, wakes, sleeps and agent creates, newest first. |
| createAgent(externalId, params?) / agents(externalId) | Create the end user's agent exactly once; list their agents. |
| setPolicy / getPolicy / clearPolicy(externalId) | Caps and sizing for every agent the end user owns. |
| mintToken(externalId, {agentId?, scopes?, ttlSeconds?}) / revokeTokens(externalId) | Short-lived eu_ token for their own client; revoke every live token. |
| suspend / resume / delete(externalId) | Pause, restore, or remove the end user with their agents. |
Projects
The HTTP front door: route each of your users' messages to their own agent. Access via maritime.projects.
| Method | Does |
|---|---|
| get(projectId) | Fetch a project. Every agent has a projectId. |
| update(projectId, {name?, newChatPolicy?, maxInstances?, warmPoolSize?}) | Routing for new end users: 'single', 'assign', 'spawn' (one agent per end user) or 'claim'. |
| message(projectId, {externalUserId, message, wait?, claimCode?, displayName?}) | Send an end user's message to their agent (bind, wake, deliver). Waits up to wait seconds (default 30) for the reply. |
| getMessage(projectId, messageId) | Poll a queued message for its reply. |
| users(projectId) / getUser(projectId, externalUserId) | Every bound end user, or one with its agent status. |
| unbindUser(projectId, externalUserId) | Unbind an end user. Their agent rejoins the warm pool. |
Swarms
Run one command on many ephemeral sandboxes and collect the results. Access via maritime.swarms (TS) / client.swarms (Python). See Swarms.
| Method | Does |
|---|---|
| start({command, count? | inputs?, name?, template? | image?, size?, timeoutSeconds?, concurrency?, resultPath?}, {idempotencyKey?}) | Start a swarm: one command on many ephemeral sandboxes. Needs the provision scope. A repeated idempotencyKey returns the first run. |
| list({limit?}) | Your runs, newest first. |
| get(swarmId) | One run with every sandbox: status, sandboxId (sbx-...), exit code, output tails and result. |
| cancel(swarmId) | Stop a run; its sandboxes are stopped and ended. |
| results(swarmId) | Every sandbox's outcome, in input order. |
| wait(swarmId, {intervalMs?, timeoutMs?}) | Poll until the run completes or is cancelled. Python takes interval and timeout in seconds. |
Keys
Mint scoped API keys programmatically. Minting requires the caller's key to carry the manage scope. Scopes are provision, deploy, secrets, manage and computers. The default is the first four, which reach Computers through manage; a key that should reach only Computers asks for ['computers']. A key created with projectId works only on that project's front door and usage routes and is refused everywhere else.
| Method | Does |
|---|---|
| create({name, scopes?, expiresInDays?, projectId?}) | Mint a key. The raw key is returned once. |
| list() | List your keys (raw values never returned again). |
| revoke(id) | Revoke a key. |
const worker = await maritime.keys.create({ name: 'chat-worker', scopes: ['deploy'] })
// worker.rawKey is shown once. Store it now.
const tenant = await maritime.keys.create({ name: 'tenant-a', projectId: agent.projectId })Webhooks
Receive signed events instead of polling. The webhooks guide lists every event and covers retries and verification.
| Method | Does |
|---|---|
| create({url, events?}) | Subscribe a URL. Returns the signing secret once. |
| list() | List subscriptions, with isActive for each. |
| deliveries(id, {status?, limit?}) | The delivery log, newest first. status is 'pending', 'delivered', 'failed' or 'dead'. |
| replay(deliveryId) | Send one delivery again now and return the result. |
| test(id) | Deliver a synthetic ping. |
| delete(id) | Remove a subscription. |
Verify a delivery with verifyWebhookSignature({secret, body, signature}) (TS, returns a Promise of boolean) or verify_webhook_signature(secret, body, signature) (Python), both exported at the package top level. Pass the raw body and the X-Maritime-Signature header.
Billing, account and network
| Method | Does |
|---|---|
| billing.usage({from?, to?, projectId?, externalUserId?}) | Per-agent hosting and AI cost over a range (at most 92 days), with externalUserId on each row. |
| billing.usageDaily({from?, to?}) | The same costs by day. |
| account.limits() | Your plan, machine counts against their caps, and per-agent size ceilings. Any key works. |
| network.presets.list() / create({name, allow?, deny?}) / delete(presetId) | Saved internet allow and deny lists to apply to agents. |
Feedback
Tell Maritime when a doc is wrong, an example does not run, or a call fails in a way you cannot explain. Built for coding agents. See the feedback guide.
| Method | Does |
|---|---|
| send({message, kind?, subject?, agentId?, requestId?, statusCode?, tool?, context?}) | Send one report. Returns the stored row (202). |
| list() | The account's last 50 reports, newest first. |
await maritime.feedback.send({
kind: 'sdk',
subject: 'agents.chat',
message: 'chat returned 500 on a fresh agent; docs say sleeping agents auto-wake.',
requestId: err.requestId,
statusCode: err.status,
tool: 'claude-code/2.1.0',
})Errors
Every failure is a subclass of MaritimeError. API errors expose .status and .detail.
| Class | When |
|---|---|
| MaritimeAuthError | 401 / 403: bad or under-scoped key |
| MaritimePaymentRequiredError | 402: plan limit reached, or an add-on needs a paid plan |
| MaritimeNotFoundError | 404: no such agent (or not yours) |
| MaritimeConflictError | 409: name already taken |
| MaritimeRateLimitError | 429: rate limited |
| MaritimeAPIError | any other non-2xx |
| MaritimeConnectionError | never reached Maritime (network / timeout) |
from maritime import MaritimeAPIError
try:
client.agents.get("nope")
except MaritimeAPIError as err:
print(err.status, err.detail, err.request_id)More resources
- Computers:
maritime.computers, desktops your own model drives - Networks: internet policy, exits and private access
- Limits: plan caps, size ceilings and error codes
- Web apps: public agent URLs, visibility and share links
See also
The Build on Maritime guide (visual walkthrough), the raw REST API, and the CLI.