SparkCloud API Reference

The SparkCloud API lets you manage containers, spaces, databases, CDN files, and AI keys programmatically. All endpoints live under /api/v1/.

Authentication

Generate an API key in your Account settings under API Keys. Keys begin with sc_live_.

Pass your key on every request:

X-API-Key: sc_live_your_key_here
# — or —
Authorization: Bearer sc_live_your_key_here
Admin endpoints (under /admin/) require the admin role on your account.

Errors

All responses are JSON. Errors return an error string. Successful mutations return a message string.

Error

{
  "error": "Container not found"
}

Success

{
  "message": "Container stopped"
}

Paginated endpoints accept ?page=1&limit=25 query parameters (max limit 100).

Account

Manage your own profile and credentials.

GET /api/v1/account

Returns your profile, credit balance, quotas, and current usage.

Response

{
  "id": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
  "username": "alice",
  "email": "alice@example.com",
  "role": "user",
  "credits": 42.5,
  "quotas": {
    "containers": { "used": 1, "limit": 3 },
    "spaces":     { "used": 0, "limit": 2 },
    "databases":  { "used": 1, "limit": 2 }
  },
  "createdAt": "2025-01-15T10:00:00.000Z"
}

PATCH /api/v1/account

Update your username and/or email address.

Request

{
  "username": "alice2",
  "email": "alice2@example.com"
}

Response

{
  "user": {
    "id": "3f2504e0...",
    "username": "alice2",
    "email": "alice2@example.com",
    "role": "user"
  }
}

POST /api/v1/account/change-password

Change your own account password.

Request

{
  "currentPassword": "oldSecret123",
  "newPassword": "newSecret456"
}

Response

{
  "message": "Password changed successfully"
}

GET /api/v1/account/transactions

Paginated credit transaction history. Query: ?page=1&limit=25

Response

{
  "transactions": [
    {
      "id": "uuid",
      "amount": -0.002,
      "type": "debit",
      "description": "Container hourly billing",
      "createdAt": "2025-03-07T12:00:00.000Z"
    }
  ],
  "page": 1,
  "limit": 25,
  "total": 84
}

GET /api/v1/account/storage

Full storage usage breakdown for your account, including quota, allocated instances, and CDN files. Running/stopped instances report their allocated disk. Hibernated instances report their actual compressed snapshot size.

Response

{
  "quota": {
    "quotaGb": 0,
    "allocatedGb": 15,
    "cdnGb": 0.12,
    "availableGb": 4.88
  },
  "totalBytes": 21474836480,
  "totalMb": 20480,
  "breakdown": {
    "containers": {
      "count": 2,
      "allocatedBytes": 10737418240,
      "snapshotBytes": 524288000,
      "totalBytes": 11261706240
    },
    "spaces": {
      "count": 1,
      "allocatedBytes": 5368709120,
      "snapshotBytes": 0,
      "totalBytes": 5368709120
    },
    "databases": {
      "count": 1,
      "allocatedBytes": 5368709120,
      "snapshotBytes": 0,
      "totalBytes": 5368709120
    },
    "backups": {
      "count": 3,
      "totalBytes": 314572800
    },
    "cdn": {
      "count": 12,
      "totalBytes": 130023424
    }
  }
}

Notifications

Platform notifications sent to your account.

GET /api/v1/notifications

List your notifications. Query: ?unread=true, ?page=1&limit=25.

Response

{
  "notifications": [
    {
      "id": "uuid",
      "title": "Container transferred",
      "message": "Your container has been moved to a new node.",
      "type": "info",
      "read": false,
      "link": "/containers/uuid",
      "createdAt": "2025-03-07T12:00:00.000Z"
    }
  ],
  "page": 1,
  "limit": 25,
  "total": 3,
  "unreadCount": 1
}

Mark Notifications Read

POST/api/v1/notifications/:id/read
POST/api/v1/notifications/read-all

Response

{ "message": "All notifications marked as read" }

Delete Notifications

DELETE/api/v1/notifications/:idDelete one
DELETE/api/v1/notificationsClear all

Response

{ "message": "All notifications cleared" }

Vouchers

Redeem voucher codes to add credits to your account.

POST /api/v1/vouchers/redeem

Redeem a voucher code. Each code can only be redeemed once per user.

Request

{ "code": "ABCD-EFGH-WXYZ" }

Response

{ "message": "Voucher redeemed successfully", "credits": 500 }

Containers

Linux containers with full SSH access, a dedicated IP, and an optional extra port.

Compute & Images

GET/api/v1/containers/plansDynamic plan info & price

SparkCloud runs a single Dynamic plan: CPU and RAM fluctuate to your workload, so there is nothing to choose at create time.

Response

{
  "plans": [
    { "id": "dynamic", "name": "Dynamic", "dynamic": true, "pricePerHour": 0.5,
      "note": "CPU and RAM fluctuate to your workload — no plan selection needed." }
  ]
}
GET/api/v1/containers/imagesList allowed images

Response

{ "images": [ { "value": "ubuntu:22.04", "label": "Spark Ubuntu 22.04 LTS" } ] }

POST /api/v1/containers

Create a new container. The container is queued immediately and typically starts within 30–60 seconds. No plan to choose — CPU and RAM scale to the node automatically.

Request

{
  "name": "my-ubuntu",
  "image": "ubuntu:22.04",
  "diskGb": 10
}

Response

{
  "container": {
    "id": "uuid",
    "name": "my-ubuntu",
    "status": "queued",
    "image": "ubuntu:22.04",
    "subdomain": "myapp",
    "host": "myapp.node1.yourdomain.com",
    "sshPort": 32100,
    "sshUser": "root",
    "sshPassword": "xK9mP2qL...",
    "hostname": "my-ubuntu",
    "extraPort": 32101,
    "ssh": {
      "host": "1.2.3.4",
      "port": 32100,
      "user": "root",
      "password": "xK9mP2qL...",
      "command": "ssh root@1.2.3.4 -p 32100"
    },
    "createdAt": "2025-01-15T10:00:00.000Z"
  },
  "message": "Container queued for deployment"
}
Only image: ubuntu:22.04 (Spark Ubuntu 22.04 LTS). Poll GET /containers/:id until status becomes running. Pass optional diskGb to allocate a specific amount of your storage quota to this container (default: 10GB).

GET /api/v1/containers

List your containers. Query: ?status=running. Statuses: running, stopped, hibernated, creating, error.

Response

{
  "containers": [
    {
      "id": "uuid",
      "name": "my-ubuntu",
      "status": "running",
      "image": "ubuntu:22.04",
      "subdomain": "myapp",
    "host": "myapp.node1.yourdomain.com",
      "sshPort": 32100,
      "sshUser": "root",
      "sshPassword": "xK9mP2qL...",
      "hostname": "my-ubuntu",
      "extraPort": 32101,
      "hibernated": false,
      "ssh": {
        "host": "1.2.3.4",
        "port": 32100,
        "user": "root",
        "password": "xK9mP2qL...",
        "command": "ssh root@1.2.3.4 -p 32100"
      },
      "plan": { "name": "Nano", "cpu": 1, "memoryMb": 512, "diskGb": 10 },
      "nodeRegion": "us-east-1",
      "createdAt": "2025-01-15T10:00:00.000Z"
    }
  ]
}

GET /api/v1/containers/:id

Full details for a single container including SSH connection command.

Response

{
  "id": "uuid",
  "name": "my-ubuntu",
  "status": "running",
  "ssh": {
    "host": "1.2.3.4",
    "port": 32100,
    "user": "root",
    "password": "xK9mP2qL...",
    "command": "ssh root@1.2.3.4 -p 32100"
  },
  "plan": { "id": "uuid", "name": "Nano", "cpu": 1, "memoryMb": 512, "diskGb": 10 },
  "nodeRegion": "us-east-1",
  "createdAt": "2025-01-15T10:00:00.000Z"
}

DELETE /api/v1/containers/:id

Permanently destroy a container and all its data.

This action is irreversible.

Response

{ "message": "Container destroyed" }

Start / Stop / Restart

POST/api/v1/containers/:id/start
POST/api/v1/containers/:id/stop
POST/api/v1/containers/:id/restart

No request body required.

Response

{ "message": "Container started" }
{ "message": "Container stopped" }
{ "message": "Container restarted" }

GET /api/v1/containers/:id/logs

Recent container logs. Query: ?tail=100 (max 500 lines).

Response

{
  "logs": "Welcome to Ubuntu 22.04
...
root@my-ubuntu:~#",
  "lines": 42
}

POST /api/v1/containers/:id/exec

Run a shell command inside a running container.

Request

{ "command": "df -h && uptime" }

Response

{
  "output": "Filesystem  Size  Used
...",
  "exitCode": 0
}

POST /api/v1/containers/:id/regenerate-password

Generate a new SSH password. Applied instantly and saved to your account.

Response

{
  "message": "Password regenerated",
  "password": "nX7kQ2mPvRtL9s3J",
  "ssh": {
    "host": "1.2.3.4",
    "port": 32100,
    "user": "root",
    "password": "nX7kQ2mPvRtL9s3J",
    "command": "ssh root@1.2.3.4 -p 32100"
  }
}

Hibernate & Wake

Hibernation snapshots the filesystem to storage and deallocates compute. Storage charges continue; CPU/RAM charges stop.

POST/api/v1/containers/:id/hibernate
POST/api/v1/containers/:id/unhibernate

Response

{ "message": "Container hibernated" }
{ "message": "Container is running" }

PATCH /api/v1/containers/:id/storage

Reallocate disk storage for a container. The new allocation is saved immediately and applied to the Docker storage quota on the next restart. Must not exceed your available storage quota.

Request

{ "diskGb": 20 }

Response

{
  "message": "Storage updated. Restart to apply.",
  "diskGb": 20
}
Check available quota first via GET /api/v1/account/storage. A restart is required for Docker to enforce the new limit.

Spaces

Browser-based VS Code environments. Auto-hibernates after 30 minutes of inactivity.

GET /api/v1/spaces/plans

Spaces run on the single Dynamic plan — CPU and RAM scale to the node automatically.

Response

{
  "plans": [
    { "id": "dynamic", "name": "Dynamic", "dynamic": true, "pricePerHour": 0.5 }
  ]
}

POST /api/v1/spaces

Create a new dev space (browser VS Code). No plan to choose — CPU and RAM scale to the node automatically.

Request

{
  "name": "my-workspace",
  "diskGb": 10
}

Response

{
  "space": {
    "id": "uuid",
    "name": "my-workspace",
    "status": "creating",
    "subdomain": "myapp",
    "host": "myapp.node1.yourdomain.com",
    "webPort": 43210,
    "createdAt": "2025-01-15T10:00:00.000Z"
  },
  "message": "Space is launching…"
}
Poll GET /spaces/:id until status is running, then open the space through the dashboard. Pass optional diskGb to allocate a specific amount of your storage quota (default: plan disk size).

GET /api/v1/spaces

List your spaces. Query: ?status=running

Response

{
  "spaces": [
    {
      "id": "uuid",
      "name": "my-workspace",
      "status": "running",
      "subdomain": "myapp",
    "host": "myapp.node1.yourdomain.com",
      "webPort": 56100,
      "hibernated": false,
      "lastActiveAt": "2025-03-07T11:45:00.000Z",
      "nodeRegion": "us-east-1",
      "createdAt": "2025-02-01T08:00:00.000Z"
    }
  ]
}

GET /api/v1/spaces/:id

Response

{
  "id": "uuid",
  "name": "my-workspace",
  "status": "running",
  "subdomain": "myapp",
    "host": "myapp.node1.yourdomain.com",
  "webPort": 56100,
  "hibernated": false,
  "lastActiveAt": "2025-03-07T11:45:00.000Z",
  "nodeRegion": "us-east-1",
  "createdAt": "2025-02-01T08:00:00.000Z"
}

DELETE /api/v1/spaces/:id

Response

{ "message": "Space deleted" }

Start / Stop

POST/api/v1/spaces/:id/start
POST/api/v1/spaces/:id/stop

Response

{ "message": "Space started" }
{ "message": "Space stopped" }

Logs & Activity

GET/api/v1/spaces/:id/logsQuery: ?tail=100

Response

{ "logs": "[16:42:05] INFO  Server listening on :8080
..." }
GET/api/v1/spaces/:id/activity

Response

{
  "lastActiveAt": "2025-03-07T11:45:00.000Z",
  "status": "running"
}

Hibernate & Wake

POST/api/v1/spaces/:id/hibernate
POST/api/v1/spaces/:id/unhibernate

Response

{ "message": "Space hibernated" }
{ "message": "Space is running" }

PATCH /api/v1/spaces/:id/storage

Reallocate disk storage for a space. Saved immediately; applied to the Docker storage quota on next restart.

Request

{ "diskGb": 15 }

Response

{
  "message": "Storage updated. Restart to apply.",
  "diskGb": 15
}

Databases

Managed PostgreSQL with automated backups, SQL Studio, and table browser.

GET /api/v1/databases/pricing

Returns the current hourly credit cost and default resource specs for a new database.

Response

{
  "pricePerHour": 1,
  "engine": "postgresql",
  "defaultDiskGb": 5,
  "defaultMemoryMb": 512,
  "defaultCpu": 1
}

POST /api/v1/databases

Provision a new PostgreSQL database. Only a name is required — resources are fixed at the defaults shown in GET /databases/pricing. Pass optional diskGb to allocate a specific amount of your storage quota (default: 5 GB).

Request

{
  "name": "my-db"
}

Response

{
  "database": {
    "id": "uuid",
    "name": "my-db",
    "status": "creating",
    "subdomain": "myapp",
    "host": "myapp.node1.yourdomain.com",
    "dbPort": 35000,
    "dbName": "sparkcloud",
    "dbUser": "sparkcloud",
    "dbPassword": "auto-generated",
    "connectionString": "postgresql://sparkcloud:pass@1.2.3.4:35000/sparkcloud",
    "createdAt": "2025-01-15T10:00:00.000Z"
  },
  "message": "Database is provisioning…"
}
Poll GET /databases/:id until status is running. The connectionString is ready to use at that point.

GET /api/v1/databases

List your databases. Query: ?status=running

Response

{
  "databases": [
    {
      "id": "uuid",
      "name": "my-postgres",
      "status": "running",
      "subdomain": "myapp",
    "host": "myapp.node1.yourdomain.com",
      "dbPort": 5432,
      "dbName": "sparkcloud",
      "dbUser": "sparkcloud",
      "dbPassword": "secret123",
      "connectionString": "postgresql://sparkcloud:secret123@1.2.3.4:5432/sparkcloud",
      "hibernated": false,
      "backupSchedule": "daily",
      "nodeRegion": "us-east-1",
      "createdAt": "2025-01-20T08:00:00.000Z"
    }
  ]
}

GET /api/v1/databases/:id

Response

{
  "id": "uuid",
  "name": "my-postgres",
  "status": "running",
  "connectionString": "postgresql://sparkcloud:secret123@1.2.3.4:5432/sparkcloud",
  "backupSchedule": "daily",
  "hibernated": false,
  "nodeRegion": "us-east-1",
  "createdAt": "2025-01-20T08:00:00.000Z"
}

DELETE /api/v1/databases/:id

All backups are also deleted. Irreversible.

Response

{ "message": "Database destroyed" }

Start / Stop / Restart

POST/api/v1/databases/:id/start
POST/api/v1/databases/:id/stop
POST/api/v1/databases/:id/restart

Response

{ "message": "Database started" }

POST /api/v1/databases/:id/reset-password

Generate a new PostgreSQL password. Applied instantly. Returns a fresh connection string.

Response

{
  "message": "Password reset",
  "newPassword": "Xk9mQ2pL...",
  "connectionString": "postgresql://sparkcloud:Xk9mQ2pL...@1.2.3.4:5432/sparkcloud"
}

PATCH /api/v1/databases/:id/backup-schedule

Request

{ "schedule": "daily" }

Values: "daily", "weekly", null

Response

{ "message": "Backup schedule set to daily" }

POST /api/v1/databases/:id/query

Execute any SQL statement. Database must be running.

Request

{ "sql": "SELECT id, name FROM users LIMIT 3" }

Response

{
  "columns": ["id", "name"],
  "rows": [["1","Alice"],["2","Bob"]],
  "rowCount": 2,
  "duration": 12
}

GET /api/v1/databases/:id/tables

All tables in the public schema with column definitions.

Response

{
  "tables": [
    {
      "name": "users",
      "columns": [
        { "name": "id",    "type": "uuid", "nullable": false },
        { "name": "email", "type": "text", "nullable": false }
      ]
    }
  ]
}

Backups

GET/api/v1/databases/:id/backupsList

Response

{
  "backups": [
    {
      "id": "uuid",
      "label": "Before migration",
      "type": "manual",
      "status": "ready",
      "sizeBytes": 2097152,
      "createdAt": "2025-03-07T10:00:00.000Z"
    }
  ]
}
POST/api/v1/databases/:id/backupsCreate manual backup

Request

{ "label": "Before migration" }

Response

{ "message": "Backup started", "backup": { "id": "uuid" } }
POST/api/v1/databases/:id/backups/:bid/restore
{ "message": "Backup restored successfully" }
DELETE/api/v1/databases/:id/backups/:bid
{ "message": "Backup deleted" }

Hibernate & Wake

POST/api/v1/databases/:id/hibernate
POST/api/v1/databases/:id/unhibernate

Response

{ "message": "Database hibernated" }
{ "message": "Database is running" }

PATCH /api/v1/databases/:id/storage

Reallocate disk storage for a database. Saved immediately; applied to the Docker storage quota on next restart.

Request

{ "diskGb": 10 }

Response

{
  "message": "Storage updated. Restart to apply.",
  "diskGb": 10
}

CDN Storage

Upload and serve files via SparkStore. Files get a permanent slug-based URL.

GET /api/v1/cdn/files

List your CDN files. Query: ?page=1&limit=25

Response

{
  "files": [
    {
      "slug": "xK9mP2qL",
      "filename": "photo.jpg",
      "size": 204800,
      "visibility": "private",
      "url": "https://cdn.example.com/api/files/xK9mP2qL",
      "createdAt": "2025-03-01T10:00:00.000Z"
    }
  ],
  "page": 1, "limit": 25, "total": 12
}

POST /api/v1/cdn/upload

All uploads are private.

Option A — multipart/form-data

curl -X POST /api/v1/cdn/upload   -H "X-API-Key: sc_live_..."   -F "file=@photo.jpg"

Option B — binary body

curl -X POST /api/v1/cdn/upload   -H "X-API-Key: sc_live_..."   -H "X-Filename: photo.jpg"   --data-binary @photo.jpg

Response

{
  "slug": "xK9mP2qL",
  "url": "https://cdn.example.com/api/files/xK9mP2qL",
  "filename": "photo.jpg",
  "size": 204800,
  "visibility": "private"
}

GET /api/v1/cdn/files/:slug

Response

{
  "slug": "xK9mP2qL",
  "filename": "photo.jpg",
  "size": 204800,
  "visibility": "private",
  "url": "https://cdn.example.com/api/files/xK9mP2qL",
  "createdAt": "2025-03-01T10:00:00.000Z"
}

DELETE /api/v1/cdn/files/:slug

Response

{ "message": "File deleted" }

AI Keys

Manage keys for SparkCloud's OpenAI-compatible proxy at /api/ai/v1/.

GET /api/v1/ai/keys

Response

{
  "keys": [
    {
      "id": "uuid",
      "name": "My App",
      "prefix": "sc-ai-3f2504e0…",
      "createdAt": "2025-02-15T10:00:00.000Z"
    }
  ]
}

POST /api/v1/ai/keys

The full key is only returned once. Store it immediately.

Request

{ "name": "Production App" }

Response

{
  "id": "uuid",
  "name": "Production App",
  "key": "sc-ai-3f2504e04f89..."
}

DELETE /api/v1/ai/keys/:id

Response

{ "message": "AI key deleted" }