REST API

RESTful API for managing agents programmatically.

Which API do I want?

  • Building a product on Maritime? Use the SDK (TypeScript/Python); it wraps everything below.
  • Driving your own agents over HTTP? This page: Bearer auth with an mk_ key.

Base URL: https://api.maritime.sh

Check it's alive (no auth needed):

GET /health
curl https://api.maritime.sh/health
# response includes {"status":"ok","runtime":"fleet"}

Authentication

Mint a personal API key with maritime keys create and send it as a Bearer token, the same token the CLI itself uses. Every authenticated endpoint on this page accepts it.

curl -H "Authorization: Bearer mk_xxxxxxxxxxxx" \
  https://api.maritime.sh/api/agents

Templates

List available agent templates. Public, no auth.

GET /api/templates
GET /api/templatespublic: works signed out

Agents

GET /api/agents
GET /api/agentslists YOUR agents via your dashboard session (the raw API returns a bare array)
POST /api/agents

Create returns 201 and starts deploying immediately. Always pass templateId (see GET /api/templates).

POST /api/agents (body)
{
  "name": "my-agent",
  "templateId": "openclaw"
}
GET /api/agents/{agent_id}
DELETE /api/agents/{agent_id}

Delete returns 204 and removes the container and its data volume.

Chat with an agent

Sends a message through the same delivery path Telegram and webhooks use. Sleeping serverless agents wake automatically; the call waits for the reply.

POST /api/agents/{agent_id}/chat
curl -X POST https://api.maritime.sh/api/agents/AGENT_ID/chat \
  -H "Authorization: Bearer mk_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"message": "summarize today"}'

# → { "response": "..." }
# Optional: pass "conversation_id" to continue a thread.

Lifecycle

Rarely needed (agents sleep and wake on their own), but available for ops:

POST /api/agents/{agent_id}/start
POST /api/agents/{agent_id}/stop
POST /api/agents/{agent_id}/sleep
POST /api/agents/{agent_id}/restart

Logs

GET /api/agents/{agent_id}/logs
curl -H "Authorization: Bearer mk_xxxxxxxxxxxx" \
  "https://api.maritime.sh/api/agents/AGENT_ID/logs?limit=100&level=error"

Files

Move files in and out of a running agent's sandbox and manage its disk. Browse, write, and organize operations are scoped to the agent's persistent volume; the response of list reports that volume's mount as root (/data for most templates), so don't hardcode it. Download accepts any absolute in-container path, since agents also produce files in /tmp and workspace directories. Any file call wakes a sleeping agent; transfers are capped at 100 MB per file.

GET /api/agents/{agent_id}/files/list?path=/data
GET /api/agents/{agent_id}/files/download?path=/data/report.pdf
POST /api/agents/{agent_id}/files/upload

Upload is multipart (file field). With a dest_dir form field the file lands in that exact volume directory; without it, it's delivered as a chat attachment: the file lands in the agent's inbox and the agent is notified in its current conversation (an optional message field rides along).

PUT /api/agents/{agent_id}/files/write
POST /api/agents/{agent_id}/files/mkdir
POST /api/agents/{agent_id}/files/move
DELETE /api/agents/{agent_id}/files/delete?path=/data/old

write takes {"path", "content"} (UTF-8 text); move takes {"from", "to"} and answers 409 if the destination exists and 404 if the source doesn't; delete of a missing path is 404, and deleting the volume root is refused.

curl -H "Authorization: Bearer mk_xxxxxxxxxxxx" \
  "https://api.maritime.sh/api/agents/AGENT_ID/files/list"
# → { "path": "/data", "root": "/data",
#     "entries": [{ "name": "notes.md", "isDir": false, "size": 182, "mtime": 1723900000 }] }

curl -X POST https://api.maritime.sh/api/agents/AGENT_ID/files/upload \
  -H "Authorization: Bearer mk_xxxxxxxxxxxx" \
  -F "file=@report.csv" -F "dest_dir=/data/inbox"
# → { "ok": true, "path": "/data/inbox/report.csv", "name": "report.csv", "size": 5321 }
These endpoints operate on the running agent's disk and never execute what you upload.

Run a command

Run a one-shot, non-interactive shell command in the agent's VM (its sandboxed container). Wakes a sleeping agent. Timeout defaults to 60s (max 120); output is one merged stream capped at 256 KB.

POST /api/agents/{agent_id}/exec
curl -X POST https://api.maritime.sh/api/agents/AGENT_ID/exec \
  -H "Authorization: Bearer mk_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"command": ["ls", "-la", "/data"], "timeout": 30}'
# → { "exitCode": 0, "stdout": "...", "stderr": "" }
# "command" is argv tokens (quoted for you) or a raw shell string.

Deploy

Redeploy an agent from a GitHub repo or a Docker image:

POST /api/deploy
POST /api/deploy (body)
{
  "agentId": "AGENT_ID",
  "source": "github",
  "repoUrl": "https://github.com/you/app",
  "branch": "main"
}

Webhooks

Every agent has an invoke URL. A POST is accepted immediately and delivered to the agent in the background, waking it first if it is asleep. Send the agent's invoke token as an X-Maritime-Webhook-Token header or a ?token= query parameter. Calls without a token still work for now but are being phased out; get the token (and a ready-to-paste URL) from the token endpoint while signed in:

POST /api/webhooks/{agent_id}

Fetch the token and a ready-to-paste URL while signed in:

GET /api/webhooks/{agent_id}/token

Invokes are rate limited per agent and caller (30/min) and share the agent's message budget, so a burst returns 429 with a Retry-After header instead of queueing.

Computers

Persistent desktops your own model drives, one per end user. These routes take a key with the computers scope and are usually reached through the MCP server; see the Computers guide.

POST /api/v1/computers
GET /api/v1/computers
GET /api/v1/computers/{computer_id}
DELETE /api/v1/computers/{computer_id}
POST /api/v1/computers/{computer_id}/wake
POST /api/v1/computers/{computer_id}/sleep
POST /api/v1/computers/{computer_id}/actions
GET /api/v1/computers/{computer_id}/screenshot
POST /api/v1/computers/{computer_id}/exec
GET /api/v1/computers/{computer_id}/files
PUT /api/v1/computers/{computer_id}/files
GET /api/v1/computers/{computer_id}/files/list
POST /api/v1/computers/{computer_id}/viewer
POST /api/v1/computers/{computer_id}/sessions/close
GET /api/v1/computers/{computer_id}/sessions
GET /api/v1/computers/usage

Looking for more?

Everything else is scriptable via the CLI. Run maritime guide --json for the full machine-readable surface. Dashboard-internal endpoints are intentionally undocumented and may change without notice.