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 /healthcurl 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/agentsTemplates
List available agent templates. Public, no auth.
GET /api/templatesAgents
GET /api/agentsPOST /api/agentsCreate returns 201 and starts deploying immediately. Always pass templateId (see GET /api/templates).
{
"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}/chatcurl -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}/startPOST /api/agents/{agent_id}/stopPOST /api/agents/{agent_id}/sleepPOST /api/agents/{agent_id}/restartLogs
GET /api/agents/{agent_id}/logscurl -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=/dataGET /api/agents/{agent_id}/files/download?path=/data/report.pdfPOST /api/agents/{agent_id}/files/uploadUpload 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/writePOST /api/agents/{agent_id}/files/mkdirPOST /api/agents/{agent_id}/files/moveDELETE /api/agents/{agent_id}/files/delete?path=/data/oldwrite 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 }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}/execcurl -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{
"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}/tokenInvokes 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/computersGET /api/v1/computersGET /api/v1/computers/{computer_id}DELETE /api/v1/computers/{computer_id}POST /api/v1/computers/{computer_id}/wakePOST /api/v1/computers/{computer_id}/sleepPOST /api/v1/computers/{computer_id}/actionsGET /api/v1/computers/{computer_id}/screenshotPOST /api/v1/computers/{computer_id}/execGET /api/v1/computers/{computer_id}/filesPUT /api/v1/computers/{computer_id}/filesGET /api/v1/computers/{computer_id}/files/listPOST /api/v1/computers/{computer_id}/viewerPOST /api/v1/computers/{computer_id}/sessions/closeGET /api/v1/computers/{computer_id}/sessionsGET /api/v1/computers/usageLooking 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.