Provisioning API

Programmatically provision agents, manage environment variables, and inject custom build scripts for enterprise deployments.

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

Auth: All provisioning endpoints require an X-API-Key header with a maritime API key (mk_...).

Quick Start

Provision an agent and deploy in a few lines.

# Set your API key
export MARITIME_API_KEY="mk_your_key_here"

# 1. Provision an agent
curl -s -X POST https://api.maritime.sh/api/v1/provision \
  -H "X-API-Key: $MARITIME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-agent",
    "image": "openclaw",
    "image_name": "python:3.11-slim",
    "auto_deploy": false
  }'

# Save the agent_id from the response, then:

# 2. Deploy the agent
curl -s -X POST https://api.maritime.sh/api/v1/agents/AGENT_ID/deploy \
  -H "X-API-Key: $MARITIME_API_KEY" \
  -H "Content-Type: application/json"

# 3. Check status
curl -s https://api.maritime.sh/api/v1/agents/AGENT_ID \
  -H "X-API-Key: $MARITIME_API_KEY"

API Key Management

Create and manage API keys from the dashboard. These endpoints use session authentication (cookies), not API key auth.

Create API Key

POST/api/v1/keys
ParameterTypeRequiredDescription
namestringYesHuman-readable name for this key
scopesstring[]NoScopes: provision, deploy, secrets, manage. Default: all.
expires_in_daysinteger | nullNoKey expiry in days. Null = never expires.
curl -X POST https://api.maritime.sh/api/v1/keys \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "production-pipeline",
    "scopes": ["provision", "deploy", "manage"],
    "expires_in_days": 90
  }'
Response: 201 Created
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "production-pipeline",
  "key_prefix": "mk_aBcDeFgH",
  "scopes": ["provision", "deploy", "manage"],
  "is_active": true,
  "last_used_at": null,
  "expires_at": "2026-06-13T10:30:00Z",
  "created_at": "2026-03-15T10:30:00Z",
  "raw_key": "mk_aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789abc"
}

Store the raw_key securely. It is returned only once at creation time and cannot be retrieved again.

List API Keys

GET/api/v1/keys
curl -s https://api.maritime.sh/api/v1/keys \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN"

Revoke API Key

DELETE/api/v1/keys/{key_id}
curl -X DELETE https://api.maritime.sh/api/v1/keys/KEY_ID \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN"

# Returns 204 No Content on success

Provisioning

Provision Agent

POST/api/v1/provisionscope: provision
ParameterTypeRequiredDescription
namestringYesAgent name
descriptionstringNoAgent description
imagestringNoFramework: openclaw, crewai, langgraph, docker, custom, auto
image_namestringNoDocker image (e.g. python:3.11-slim)
repo_urlstringNoGitHub repo URL for source builds
branchstringNoGit branch (default: main)
auto_deploybooleanNoDeploy immediately (default: true)
env_varsobjectNoNon-secret env vars as key-value pairs
curl -X POST https://api.maritime.sh/api/v1/provision \
  -H "X-API-Key: $MARITIME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "customer-support-bot",
    "image": "openclaw",
    "image_name": "python:3.11-slim",
    "repo_url": "https://github.com/acme/support-agent",
    "auto_deploy": true,
    "env_vars": {
      "LOG_LEVEL": "info",
      "REGION": "us-east-1"
    }
  }'
Response: 201 Created
{
  "agent_id": "7f3a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
  "name": "customer-support-bot",
  "status": "deploying",
  "deployment_id": "d8e9f0a1-b2c3-4d5e-6f7a-8b9c0d1e2f3a",
  "message": "Agent provisioned."
}

List Agents

GET/api/v1/agentsscope: provision
curl -s https://api.maritime.sh/api/v1/agents \
  -H "X-API-Key: $MARITIME_API_KEY"

Get Agent Status

GET/api/v1/agents/{agent_id}scope: provision
curl -s https://api.maritime.sh/api/v1/agents/AGENT_ID \
  -H "X-API-Key: $MARITIME_API_KEY"

Custom Build Files

Upload Custom Files

POST/api/v1/agents/{agent_id}/filesscope: deploy

Inject files into the agent container. By default, files are placed in /maritime/scripts/ and shell scripts are executed after deploy. You can customize the target directory and control whether scripts run on deploy.

ParameterTypeRequiredDescription
filesCustomFile[]YesArray of files to inject
files[].pathstringYesFilename or relative path (e.g. install-tools.sh, config/app.toml)
files[].contentstringYesFile content. Include shebang for scripts.
files[].executablebooleanNochmod +x the file (default: true)
files[].run_on_deploybooleanNoExecute .sh files after deploy (default: true). Set false to only place the file.
files[].target_dirstringNoDirectory inside the container (default: /maritime/scripts). E.g. /app/config, /data.
curl -X POST https://api.maritime.sh/api/v1/agents/AGENT_ID/files \
  -H "X-API-Key: $MARITIME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "files": [
      {
        "path": "install-deps.sh",
        "content": "#!/bin/bash\nset -e\napt-get update -qq\napt-get install -y -qq ffmpeg imagemagick\npip install -q pandas numpy scikit-learn",
        "executable": true,
        "run_on_deploy": true,
        "target_dir": "/maritime/scripts"
      },
      {
        "path": "app.toml",
        "content": "[server]\nhost = \"0.0.0.0\"\nport = 8080",
        "executable": false,
        "run_on_deploy": false,
        "target_dir": "/app/config"
      }
    ]
  }'

# Response: 201 Created
# {"agent_id": "...", "files_count": 2, "message": "Uploaded 2 custom file(s)..."}

Environment Variables

Manage an agent's environment variables. Secret values are stored encrypted and always returned masked. Changes apply on the agent's next container boot (redeploy or restart to pick them up).

List Environment Variables

GET/api/v1/agents/{agent_id}/env
Response: 200 OK
[
  { "key": "OPENAI_API_KEY", "value": "sk-••••••••", "is_secret": true },
  { "key": "LOG_LEVEL", "value": "debug", "is_secret": false }
]

Set an Environment Variable

POST/api/v1/agents/{agent_id}/envscope: manage

Creates the variable, or updates it if the key already exists (upsert).

ParameterTypeRequiredDescription
keystringYesVariable name
valuestringYesVariable value
is_secretbooleanNoEncrypt at rest and mask in responses (default: false)
curl -X POST https://api.maritime.sh/api/v1/agents/AGENT_ID/env \
  -H "X-API-Key: $MARITIME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key": "OPENAI_API_KEY", "value": "sk-...", "is_secret": true}'

# Response: 201 Created
# {"key": "OPENAI_API_KEY", "value": "sk-••••••••", "is_secret": true}

Update / Delete an Environment Variable

PUT/api/v1/agents/{agent_id}/env/{key}scope: manage
DELETE/api/v1/agents/{agent_id}/env/{key}scope: manage
terminal
# Update (404 if the key does not exist):
curl -X PUT https://api.maritime.sh/api/v1/agents/AGENT_ID/env/LOG_LEVEL \
  -H "X-API-Key: $MARITIME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"value": "info"}'

# Delete (returns 204 No Content):
curl -X DELETE https://api.maritime.sh/api/v1/agents/AGENT_ID/env/LOG_LEVEL \
  -H "X-API-Key: $MARITIME_API_KEY"

Lifecycle Management

Deploy / Redeploy

POST/api/v1/agents/{agent_id}/deployscope: deploy

Returns 202 Accepted: the deploy runs asynchronously. Poll GET /api/v1/agents/{agent_id} until the status leaves deploying.

ParameterTypeRequiredDescription
image_namestringNoOverride Docker image
repo_urlstringNoOverride repo URL
branchstringNoOverride git branch
# Deploy with defaults (uses provisioned settings)
curl -X POST https://api.maritime.sh/api/v1/agents/AGENT_ID/deploy \
  -H "X-API-Key: $MARITIME_API_KEY"

# Deploy a specific branch
curl -X POST https://api.maritime.sh/api/v1/agents/AGENT_ID/deploy \
  -H "X-API-Key: $MARITIME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"branch": "staging"}'

Start / Stop / Restart

POST/api/v1/agents/{agent_id}/startscope: deploy
POST/api/v1/agents/{agent_id}/stopscope: deploy
POST/api/v1/agents/{agent_id}/restartscope: deploy
# Start
curl -X POST https://api.maritime.sh/api/v1/agents/AGENT_ID/start \
  -H "X-API-Key: $MARITIME_API_KEY"

# Stop
curl -X POST https://api.maritime.sh/api/v1/agents/AGENT_ID/stop \
  -H "X-API-Key: $MARITIME_API_KEY"

# Restart
curl -X POST https://api.maritime.sh/api/v1/agents/AGENT_ID/restart \
  -H "X-API-Key: $MARITIME_API_KEY"

Teardown

DELETE/api/v1/agents/{agent_id}scope: manage

Stops the container, removes the volume, and deletes the agent record.

curl -X DELETE https://api.maritime.sh/api/v1/agents/AGENT_ID \
  -H "X-API-Key: $MARITIME_API_KEY"

# Returns 204 No Content on success

Logs & Deployments

Get Agent Logs

GET/api/v1/agents/{agent_id}/logs
ParameterTypeRequiredDescription
limitintegerNoMax entries to return (default: 100, max: 1000)
levelstringNoFilter by level: info, warning, error
curl -s "https://api.maritime.sh/api/v1/agents/AGENT_ID/logs?limit=50&level=error" \
  -H "X-API-Key: $MARITIME_API_KEY"
Response: 200 OK
[
  {
    "id": "a1b2c3d4...",
    "level": "error",
    "message": "Container exited with code 1",
    "source": "system",
    "timestamp": "2026-03-22T14:30:00Z"
  }
]

Get Deployment History

GET/api/v1/agents/{agent_id}/deployments
ParameterTypeRequiredDescription
limitintegerNoMax entries to return (default: 10, max: 50)
curl -s "https://api.maritime.sh/api/v1/agents/AGENT_ID/deployments?limit=5" \
  -H "X-API-Key: $MARITIME_API_KEY"
Response: 200 OK
[
  {
    "id": "d8e9f0a1...",
    "status": "success",
    "source": "docker",
    "branch": null,
    "build_log": "Pulling image ghcr.io/openclaw/openclaw:latest...\nContainer created: abc123...\nCustom files injected: install-deps.sh → /maritime/scripts (executed)\nDeploy complete.",
    "started_at": "2026-03-22T14:00:00Z",
    "completed_at": "2026-03-22T14:00:45Z"
  }
]

Billing

There is no billing surface on this API. Every account is on a seat plan, managed from the Billing page in the dashboard: the plan sets how many agents you may run, and add-ons (extra RAM, extra SSD, always-on) are flat monthly prices per agent. Agents you provision here count against the same plan. See Billing & plans.

API Key Scopes

ScopeGrants Access To
provisionProvision new agents, list agents, get agent status
deployDeploy, start, stop, restart agents; upload custom files
manageAll of the above, plus teardown/delete agents

Error Responses

StatusMeaning
401Missing, invalid, revoked, or expired API key
403API key lacks the required scope for this endpoint
404Agent not found, or agent belongs to a different user
409Deploy already in progress for this agent

Full End-to-End Example

Complete scripts you can copy, fill in your key, and run.

"""
maritime_provision.py: Provision, add build scripts, deploy.
pip install requests
"""
import requests

API_KEY = "mk_your_key_here"
BASE = "https://api.maritime.sh/api/v1"
H = {"X-API-Key": API_KEY, "Content-Type": "application/json"}

# ── 1. Provision (env var secret values are encrypted at rest) ──
r = requests.post(f"{BASE}/provision", headers=H, json={
    "name": "fraud-detector",
    "image": "openclaw",
    "image_name": "python:3.11-slim",
    "repo_url": "https://github.com/acme/fraud-detector",
    "auto_deploy": False,
    "env_vars": {
        "LOG_LEVEL": "info",
        "OPENAI_API_KEY": "sk-proj-...",
        "DATABASE_URL": "postgresql://user:pass@host:5432/db",
    },
}).json()
agent_id = r["agent_id"]
print(f"1. Provisioned: {agent_id}")

# ── 2. Custom build files ──
r = requests.post(f"{BASE}/agents/{agent_id}/files", headers=H, json={
    "files": [{
        "path": "install-deps.sh",
        "content": "#!/bin/bash\nset -e\napt-get update -qq\napt-get install -y -qq ffmpeg\npip install -q torch",
        "executable": True,
        "run_on_deploy": True,
    }],
}).json()
print(f"2. Files: {r['message']}")

# ── 3. Deploy ──
r = requests.post(f"{BASE}/agents/{agent_id}/deploy", headers=H).json()
print(f"3. Deploy: {r['message']} (deployment_id: {r['deployment_id']})")

# ── 4. Poll status ──
import time
for _ in range(30):
    status = requests.get(f"{BASE}/agents/{agent_id}", headers=H).json()["status"]
    print(f"   Status: {status}")
    if status in ("active", "error"):
        break
    time.sleep(5)