Overview
The MyOpenClaw Developer API lets you manage your instance programmatically. All endpoints are under /api/v1 and require Bearer token authentication with an API key.
API access is available to Pro ($49/mo) and Business ($99/mo) subscribers. Keys are created from the Dashboard or via the API itself.
Quick Start
Get up and running in under a minute. You need a Pro or Business plan and an API key from the Dashboard.
1Set your API key
Store your key as an environment variable so it stays out of your code:
export MOC_API_KEY="moc_abc123_yourSecretKeyHere"2Check your instance status
Make your first API call to verify everything works. Replace alice with your username:
curl -s -H "Authorization: Bearer $MOC_API_KEY" \
https://www.myopenclaw.cloud/api/v1/instances/alice | jq{
"id": "uuid",
"username": "alice",
"status": "running",
"domain": "alice.myopenclaw.cloud",
"plan": "pro"
}3Start or stop your instance
Control your instance with a single command:
# Stop your instance
curl -X POST -H "Authorization: Bearer $MOC_API_KEY" \
https://www.myopenclaw.cloud/api/v1/instances/alice/stop
# Start it back up (async — returns an operation ID)
curl -X POST -H "Authorization: Bearer $MOC_API_KEY" \
https://www.myopenclaw.cloud/api/v1/instances/alice/startAuthentication
Include your API key as a Bearer token in the Authorization header:
Authorization: Bearer moc_<shortToken>_<longToken>Key format
Keys use a three-part format: moc_<shortToken>_<longToken>
moc_— fixed prefix for identificationshortToken— used for fast DB lookup (not secret)longToken— HMAC-SHA256 hashed server-side; never stored in plaintext
Scopes
Each API key has a set of scopes controlling what it can access:
| Scope | Description |
|---|---|
instance:read | Read instance status |
instance:write | Start, stop, restart instances |
provider:read | Read provider/model configuration |
provider:write | Update provider/model configuration |
integrations:read | Read integration settings |
integrations:write | Update integration settings |
agents:read | Read agent configurations |
agents:write | Update agent configurations |
operations:read | Poll async operation status |
keys:read | List and view API keys |
keys:write | Create and revoke API keys |
Shortcuts
| Shortcut | Expands to |
|---|---|
read | All :read scopes |
write | All scopes |
all | All scopes |
Rate Limits
Rate limits are enforced per API key and per user (global ceiling across all keys).
Per-key limits (requests per minute)
| Operation | Pro | Business |
|---|---|---|
| Read (GET) | 120/min | 240/min |
| Write (POST, DELETE) | 30/min | 60/min |
| Heavy (start, restart) | 5/min | 10/min |
Global ceiling (per user, all keys)
| Plan | Limit |
|---|---|
| Pro | 1,000/min |
| Business | 2,000/min |
Response headers
X-RateLimit-Limit— Maximum requests allowedX-RateLimit-Remaining— Requests remainingX-RateLimit-Reset— Unix timestamp when window resetsRetry-After— Seconds to wait (on 429 responses)
Errors
All errors return a consistent JSON format:
{
"error": "Human-readable message",
"code": "ERROR_CODE"
}| HTTP | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid input |
| 400 | NOT_PROVISIONED | Instance not fully provisioned |
| 400 | CANNOT_REVOKE_SELF | A key cannot revoke itself |
| 401 | INVALID_API_KEY | Missing, invalid, revoked, or expired key |
| 402 | PAYMENT_REQUIRED | Subscription needed |
| 403 | PLAN_REQUIRED | Requires Pro or Business plan |
| 403 | INSUFFICIENT_SCOPE | Key lacks required scope |
| 403 | SCOPE_ESCALATION | Cannot create key with broader scopes |
| 404 | NOT_FOUND | Resource not found |
| 409 | ALREADY_RUNNING | Instance already running |
| 409 | ALREADY_STOPPED | Instance already stopped |
| 409 | NOT_RUNNING | Instance must be running |
| 422 | KEY_LIMIT_REACHED | Max API keys reached |
| 429 | RATE_LIMITED | Too many requests |
| 500 | INTERNAL_ERROR | Server error |
| 503 | SERVICE_UNAVAILABLE | Temporary outage |
Instances
/api/v1/instances/:instanceIdGet the current status of an instance. The :instanceId accepts a UUID or username.
Scope: instance:read
// Response 200
{
"id": "uuid",
"username": "alice",
"subdomain": "alice.myopenclaw.cloud",
"domain": "alice.myopenclaw.cloud",
"status": "running",
"plan": "pro",
"fly_region": "dfw",
"openclaw_version": "2026.2.26",
"created_at": "2026-02-01T00:00:00.000Z",
"updated_at": "2026-02-28T12:00:00.000Z"
}Statuses: provisioning, pending_payment, running, stopped, failed
/api/v1/instances/:instanceId/startAsynchronously starts a stopped instance. Returns 202 Accepted with an operation ID for polling.
Scope: instance:write · Optional: Idempotency-Key header
// Response 202
{
"operation": {
"id": "op_abc123def456",
"type": "instance.start",
"status": "pending",
"created_at": "2026-03-01T00:00:00.000Z"
},
"links": {
"poll": "/api/v1/operations/op_abc123def456"
}
}Errors: 409 ALREADY_RUNNING, 402 PAYMENT_REQUIRED, 400 NOT_PROVISIONED
/api/v1/instances/:instanceId/stopSynchronously stops a running instance. Returns immediately.
Scope: instance:write
// Response 200
{
"id": "uuid",
"status": "stopped",
"domain": "alice.myopenclaw.cloud"
}/api/v1/instances/:instanceId/restartAsynchronously restarts a running instance. Returns 202 Accepted.
Scope: instance:write · Optional: Idempotency-Key header
Error: 409 NOT_RUNNING
Operations
Async operations (start, restart) return a 202 with an operation ID. Poll this endpoint to check progress.
/api/v1/operations/:operationIdPoll the status of a single async operation. Pending/running operations include a Retry-After: 5 header. Completed operations include Cache-Control: public, max-age=3600.
Scope: operations:read
// Response 200 — succeeded
{
"id": "op_abc123def456",
"type": "instance.start",
"status": "succeeded",
"result": {
"success": true,
"domain": "alice.myopenclaw.cloud",
"version": "2026.2.26"
},
"created_at": "2026-03-01T00:00:00.000Z",
"completed_at": "2026-03-01T00:01:30.000Z"
}
// Response 200 — failed
{
"id": "op_abc123def456",
"type": "instance.start",
"status": "failed",
"error": {
"code": "FLY_API_ERROR",
"message": "Failed to start machine"
},
"created_at": "2026-03-01T00:00:00.000Z",
"completed_at": "2026-03-01T00:00:45.000Z"
}/api/v1/operationsList async operations for the authenticated user.
Query params: status (pending, running, succeeded, failed), limit (1-100, default 20)
// Response 200
{
"operations": [ ... ],
"has_more": false
}API Keys
/api/v1/keysCreate a new API key. The full key is returned only once.
Scope: keys:write
// Request body
{
"name": "CI/CD Pipeline", // 1-64 characters, required
"scopes": ["instance:read", "instance:write"], // required
"expires_in_days": 90 // 1-365, optional
}// Response 201
{
"id": "key_abc123",
"name": "CI/CD Pipeline",
"key": "moc_abc123_longSecretToken",
"short_token": "abc123",
"scopes": ["instance:read", "instance:write"],
"last_used_at": null,
"created_at": "2026-03-01T00:00:00.000Z",
"expires_at": "2026-05-30T00:00:00.000Z",
"revoked_at": null
}/api/v1/keysList all API keys for the authenticated user. Does not include secret material.
Scope: keys:read
/api/v1/keys/:keyIdGet a single API key by ID.
Scope: keys:read
/api/v1/keys/:keyIdRevoke an API key. Revocation is immediate and permanent. A key cannot revoke itself.
Scope: keys:write
// Response 200
{
"id": "key_abc123",
"revoked_at": "2026-03-01T12:00:00.000Z"
}Idempotency
For async operations (start, restart), include an Idempotency-Key header to prevent duplicate operations:
Idempotency-Key: my-unique-key-123If an operation already exists with the same idempotency key for your user, the existing operation is returned instead of creating a new one — regardless of the existing operation's current status.
Examples
Quick start (curl)
# Get instance status
curl -H "Authorization: Bearer $MOC_KEY" \
https://www.myopenclaw.cloud/api/v1/instances/alice
# Stop instance
curl -X POST -H "Authorization: Bearer $MOC_KEY" \
https://www.myopenclaw.cloud/api/v1/instances/alice/stop
# Start instance (async — returns operation ID)
curl -X POST -H "Authorization: Bearer $MOC_KEY" \
https://www.myopenclaw.cloud/api/v1/instances/alice/start
# Poll operation
curl -H "Authorization: Bearer $MOC_KEY" \
https://www.myopenclaw.cloud/api/v1/operations/op_abc123
# Create a new API key
curl -X POST -H "Authorization: Bearer $MOC_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"My Key","scopes":["read"]}' \
https://www.myopenclaw.cloud/api/v1/keys
# Revoke a key
curl -X DELETE -H "Authorization: Bearer $MOC_KEY" \
https://www.myopenclaw.cloud/api/v1/keys/key_abc123Polling pattern (Python)
import time
import requests
BASE = "https://www.myopenclaw.cloud/api/v1"
HEADERS = {"Authorization": "Bearer moc_xxx_yyy"}
# 1. Start the instance
resp = requests.post(f"{BASE}/instances/alice/start", headers=HEADERS)
operation = resp.json()["operation"]
# 2. Poll until complete
while operation["status"] in ("pending", "running"):
time.sleep(5) # Respect Retry-After header
resp = requests.get(
f"{BASE}/operations/{operation['id']}",
headers=HEADERS
)
operation = resp.json()
# 3. Check result
if operation["status"] == "succeeded":
print("Started:", operation["result"]["domain"])
else:
print("Failed:", operation["error"]["message"])Polling pattern (JavaScript)
const BASE = "https://www.myopenclaw.cloud/api/v1";
const headers = { Authorization: "Bearer moc_xxx_yyy" };
// 1. Start the instance
const startRes = await fetch(`${BASE}/instances/alice/start`, {
method: "POST",
headers,
});
let operation = (await startRes.json()).operation;
// 2. Poll until complete
while (["pending", "running"].includes(operation.status)) {
await new Promise((r) => setTimeout(r, 5000));
const pollRes = await fetch(
`${BASE}/operations/${operation.id}`,
{ headers }
);
operation = await pollRes.json();
}
// 3. Check result
if (operation.status === "succeeded") {
console.log("Started:", operation.result.domain);
} else {
console.error("Failed:", operation.error.message);
}