Endpoints
Base URL: https://api.magpiecloud.com/api/v1
Submit Job
POST
/api/v1/mags-jobs
Creates a VM, runs a script, and returns. The VM boots in ~300ms from a pool.
Request body
Field Type Required Description
script
string
YES
Shell script to execute inside the VM.
type
string
YES
Always "inline".
workspace_id
string
no
Workspace name. With persistent: false, data stays local to the VM only. With persistent: true, filesystem changes are synced to S3 and restored on next run. Omit for ephemeral.
base_workspace_id
string
no
Mount an existing workspace read-only as the starting filesystem.
persistent
bool
no
If true, VM stays alive after script finishes and workspace is synced to S3. Required for cloud persistence.
no_sleep
bool
no
If true, VM will never be auto-slept by the idle timeout. Requires persistent: true.
startup_command
string
no
Command to run when a sleeping persistent VM wakes up.
environment
object
no
Key-value env vars injected into the VM.
file_ids
string[]
no
File IDs from the upload endpoint. Files are downloaded into /root/ before script runs.
disk_gb
int
no
Custom disk size in GB. Default is 2GB. The rootfs is resized on-the-fly after VM boot.
Response (202)
{
"request_id": "eab1e214-39c8-4ecc-b941-75551976e0fa",
"status": "accepted",
"message": "Mags job submitted successfully"
}
SDK examples
curl
Python
Node.js
curl -X POST https://api.magpiecloud.com/api/v1/mags-jobs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"script": "echo hello",
"type": "inline",
"workspace_id": "myproject"
}'
job = m.run("echo hello", workspace_id="myproject")
print(job["request_id"])
# Or run and wait for completion:
result = m.run_and_wait("echo hello", workspace_id="myproject")
print(result["status"]) # "completed"
const job = await mags.run('echo hello', { workspaceId: 'myproject' });
console.log(job.requestId);
// Or run and wait:
const result = await mags.runAndWait('echo hello', { workspaceId: 'myproject' });
console.log(result.status); // "completed"
Get Job Status
GET
/api/v1/mags-jobs/:id/status
Poll this endpoint to wait for job completion.
Response (200)
{
"request_id": "eab1e214-...",
"status": "running",
"vm_id": "a488ceef",
"persistent": true,
"subdomain": "28dfed70c32e",
"url": "https://28dfed70c32e.apps.magpiecloud.com",
"sleeping": false,
"exit_code": 0,
"script_duration_ms": 1200
}
Status values
Status Description
pendingJob queued, waiting for VM.
runningScript is executing.
completedScript finished successfully.
errorScript failed or VM error.
sleepingPersistent VM is idle. Auto-wakes on next request.
SDK examples
curl
Python
Node.js
curl https://api.magpiecloud.com/api/v1/mags-jobs/$ID/status \
-H "Authorization: Bearer $TOKEN"
status = m.status("eab1e214-...")
print(status["status"]) # "running"
const status = await mags.status('eab1e214-...');
console.log(status.status); // "running"
Get Job Logs
GET
/api/v1/mags-jobs/:id/logs
Response (200)
{
"logs": [
{ "timestamp": "...", "level": "info", "message": "hello world", "source": "stdout" },
{ "timestamp": "...", "level": "error", "message": "warning: ...", "source": "stderr" }
]
}
SDK examples
curl
Python
Node.js
curl https://api.magpiecloud.com/api/v1/mags-jobs/$ID/logs \
-H "Authorization: Bearer $TOKEN"
logs = m.logs("eab1e214-...")
for log in logs["logs"]:
print(f"[{log['source']}] {log['message']}")
const logs = await mags.logs('eab1e214-...');
logs.logs.forEach(l => console.log(`[${l.source}] ${l.message}`));
List Jobs
GET
/api/v1/mags-jobs?page=1&page_size=20
Response (200)
{
"jobs": [{ "request_id": "...", "status": "completed", "workspace_id": "my-project", ... }],
"total": 42,
"page": 1,
"page_size": 20
}
SDK examples
curl
Python
Node.js
curl "https://api.magpiecloud.com/api/v1/mags-jobs?page=1&page_size=10" \
-H "Authorization: Bearer $TOKEN"
resp = m.list_jobs(page=1, page_size=10)
for job in resp["jobs"]:
print(job["request_id"], job["status"])
const resp = await mags.list({ page: 1, pageSize: 10 });
resp.jobs.forEach(j => console.log(j.requestId, j.status));
Stop Job
POST
/api/v1/mags-jobs/:id/stop
Stop a running or sleeping job. The VM is terminated and the workspace is synced to S3 if persistent.
Response (200)
{ "success": true, "message": "Job stopped" }
SDK examples
curl
Python
Node.js
CLI
curl -X POST https://api.magpiecloud.com/api/v1/mags-jobs/$ID/stop \
-H "Authorization: Bearer $TOKEN"
m.stop("myproject") # accepts name, workspace ID, or request ID
await mags.stop('myproject'); // accepts name, workspace ID, or request ID
Enable Access (SSH or HTTP)
POST
/api/v1/mags-jobs/:id/access
Enables external access to a running VM. Use port: 22 for SSH, any other port for HTTP proxy.
Request body
{ "port": 22 }
Response — SSH (port 22)
{
"success": true,
"ssh_host": "api.magpiecloud.com",
"ssh_port": 40000,
"ssh_private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n...",
"access_type": "ssh_proxy"
}
Response — HTTP (other ports)
{
"success": true,
"ipv6_address": "2a01:4f9:...",
"port": 8080,
"access_type": "http_proxy"
}
SDK examples
curl
Python
Node.js
curl -X POST https://api.magpiecloud.com/api/v1/mags-jobs/$ID/access \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "port": 22 }'
# SSH access
ssh = m.enable_access(request_id, port=22)
print(f"ssh root@{ssh['ssh_host']} -p {ssh['ssh_port']}")
# HTTP access
access = m.enable_access(request_id, port=8080)
print(access.get("url"))
// SSH access
const ssh = await mags.enableAccess(requestId, 22);
console.log(`ssh root@${ssh.sshHost} -p ${ssh.sshPort}`);
// HTTP access
const access = await mags.enableAccess(requestId, 8080);
Update Job
PATCH
/api/v1/mags-jobs/:id
Update a job's settings. All fields are optional — only include the ones you want to change.
Request body
Field Type Description
startup_commandstring Command to run when VM wakes from sleep
no_sleepbool If true, VM never auto-sleeps. If false, re-enables auto-sleep. Requires persistent VM.
{ "no_sleep": true }
SDK examples
curl
CLI
Python
Node.js
# Enable no-sleep
curl -X PATCH https://api.magpiecloud.com/api/v1/mags-jobs/$ID \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "no_sleep": true }'
# Set startup command
curl -X PATCH https://api.magpiecloud.com/api/v1/mags-jobs/$ID \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "startup_command": "python3 -m http.server 8080" }'
# Enable no-sleep on an existing VM
mags set myvm --no-sleep
# Re-enable auto-sleep
mags set myvm --sleep
# Enable no-sleep
m.update_job(request_id, no_sleep=True)
# Set startup command
m.update_job(request_id, startup_command="python3 -m http.server 8080")
await mags.updateJob(requestId, { noSleep: true });
Upload File
POST
/api/v1/mags-files
Upload a file (max 100MB) that can be attached to jobs via file_ids.
Request
Content-Type: multipart/form-data
Field name: file
Response (201)
{
"file_id": "a1b2c3d4-...",
"file_name": "script.py",
"size": 4096
}
SDK examples
curl
Python
Node.js
curl -X POST https://api.magpiecloud.com/api/v1/mags-files \
-H "Authorization: Bearer $TOKEN" \
-F "file=@script.py"
file_id = m.upload_file("script.py")
file_ids = m.upload_files(["script.py", "data.csv"])
const fileId = await mags.uploadFile('script.py');
Sync Workspace
POST
/api/v1/mags-jobs/:id/sync
Trigger an immediate workspace sync to S3 without stopping the VM.
Response (200)
{ "success": true, "message": "Sync initiated" }
SDK examples
Python
Node.js
CLI
await mags.sync(requestId);
List Workspaces
GET
/api/v1/mags-workspaces
List all persistent workspaces for the authenticated user.
Response (200)
{
"workspaces": [
{ "workspace_id": "myproject", "job_count": 12, "last_used": "2026-02-04T...", "has_active": false }
],
"total": 3
}
SDK examples
curl
Python
Node.js
CLI
curl https://api.magpiecloud.com/api/v1/mags-workspaces \
-H "Authorization: Bearer $TOKEN"
ws = m.list_workspaces()
for w in ws["workspaces"]:
print(w["workspace_id"], w["job_count"])
const ws = await mags.listWorkspaces();
ws.workspaces.forEach(w => console.log(w.workspaceId));
Delete Workspace
DELETE
/api/v1/mags-workspaces/:id
Permanently delete a workspace and all its S3 data. Active jobs using this workspace must be stopped first.
Response (200)
{ "success": true, "message": "Workspace 'myproject' deleted" }
Error (409 Conflict)
{ "error": "workspace 'myproject' has 1 active job(s); stop them first" }
SDK examples
Python
CLI
curl
m.delete_workspace("myproject")
mags workspace delete myproject
mags workspace delete myproject --force # skip confirmation
curl -X DELETE https://api.magpiecloud.com/api/v1/mags-workspaces/myproject \
-H "Authorization: Bearer $TOKEN"
URL Aliases
POST
/api/v1/mags-url-aliases
GET
/api/v1/mags-url-aliases
DELETE
/api/v1/mags-url-aliases/:subdomain
Create stable, human-readable URL aliases for your sandboxes. Aliases point to a workspace and automatically follow the active VM.
Create request body
Field Type Required Description
subdomainstring YES Subdomain for the alias (e.g. my-api).
workspace_idstring YES Workspace to point the alias at.
domainstring no Custom domain (default: apps.magpiecloud.com).
SDK examples
CLI
Python
Node.js
# Create alias
mags url alias my-api myproject
# List aliases
mags url alias list
# Delete alias
mags url alias remove my-api
m.url_alias_create("my-api", "myproject")
aliases = m.url_alias_list()
m.url_alias_delete("my-api")
await mags.urlAliasCreate('my-api', 'myproject');
const aliases = await mags.urlAliasList();
await mags.urlAliasDelete('my-api');
Cron Jobs
POST
/api/v1/mags-cron
GET
/api/v1/mags-cron
PATCH
/api/v1/mags-cron/:id
DELETE
/api/v1/mags-cron/:id
Create, list, update, and delete scheduled cron jobs.
Create request body
Field Type Required Description
namestring YES Name for the cron job.
cron_expressionstring YES Standard cron expression (e.g. 0 * * * *).
scriptstring YES Script to run on each trigger.
workspace_idstring no Workspace to use.
persistentbool no Keep VM alive after script.
SDK examples
curl
Python
Node.js
CLI
curl -X POST https://api.magpiecloud.com/api/v1/mags-cron \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "nightly-backup",
"cron_expression": "0 0 * * *",
"script": "tar czf backup.tar.gz /data",
"workspace_id": "backups"
}'
cron = m.cron_create(
name="nightly-backup",
cron_expression="0 0 * * *",
script="tar czf backup.tar.gz /data",
workspace_id="backups",
)
jobs = m.cron_list()
m.cron_update(cron["id"], enabled=False)
m.cron_delete(cron["id"])
const cron = await mags.cronCreate({
name: 'nightly-backup',
cronExpression: '0 0 * * *',
script: 'tar czf backup.tar.gz /data',
workspaceId: 'backups',
});
await mags.cronDelete(cron.id);
mags cron add --name "nightly-backup" --schedule "0 0 * * *" -w backups \
'tar czf backup.tar.gz /data'
mags cron list
mags cron remove <id>