Cloud API Reference

All endpoints live under /api/cloud-saas and require Bearer token authentication.

Templates

List templates

GET /api/cloud-saas/templates
QueryTypeDescription
categorystringFilter by category
qstringSearch query
localestringLanguage for localized content (default 'en')

Returns approved templates (official + community), sorted by category and score.

Response:

{
  "templates": [
    {
      "slug": "web-app",
      "name": "Web Application",
      "description": "A full-stack web app...",
      "category": "web",
      "tags": ["react", "node"],
      "content": {},
      "author": { "username": "..." },
      "rating": 4.5,
      "deployCount": 123,
      "createdAt": "2025-01-01T00:00:00.000Z"
    }
  ],
  "categories": ["web", "api", "bot"]
}

Get template

GET /api/cloud-saas/templates/:slug
QueryTypeDescription
localestringLanguage (default 'en')

Returns a single approved template with full content. Supports server-rendered i18n descriptions.


Get template env refs

GET /api/cloud-saas/templates/:slug/env-refs

Returns the template's declared environment variables, form fields, and auto-detected env references.

Response:

{
  "envVars": [{ "key": "OPENAI_API_KEY", "description": "...", "secret": true }],
  "fields": [{ "key": "domain", "label": "Domain", "type": "text" }],
  "autoDetected": [{ "key": "DATABASE_URL", "source": "plugin:postgres" }]
}

My templates

GET /api/cloud-saas/templates/mine GET /api/cloud-saas/templates/mine/:slug

List or get templates authored by the current user, including pending/rejected ones. Same response shape as public templates.


Create template

POST /api/cloud-saas/templates
FieldTypeRequiredDescription
slugstringYesKebab-case identifier (1–255 chars)
namestringYesDisplay name (1–255 chars)
descriptionstringNoMarkdown description
contentobjectYesCloudConfig snapshot
tagsstring[]NoUp to 20 tags
categorystringNoCategory name (≤64 chars)
baseCostnumberNoEstimated monthly cost in Shrimp Coins

Content is validated against the template policy allowlist. Templates are submitted for review as pending.

Update template

PUT /api/cloud-saas/templates/:slug

Same fields as create, all optional. Only allowed for the author when the template is draft or rejected.

Submit for review

POST /api/cloud-saas/templates/:slug/submit

Re-submits a draft or rejected template for review. No body required.

Delete template

DELETE /api/cloud-saas/templates/:slug

Deletes own template at any review status.


Deployments

List deployments

GET /api/cloud-saas/deployments
QueryTypeDescription
limitnumberMax results (50 default, 100 max)
offsetnumberPagination offset (0 default)
includeOrphans'1'Include orphaned namespaces without DB rows
includeHistory'1'Include all historical deployment entries

Returns the newest visible deployment per namespace. Uses a per-namespace deduplication strategy.

Get deployment costs

GET /api/cloud-saas/deployments/costs

Returns aggregate cost snapshots for all visible SaaS deployments.

Create deployment

POST /api/cloud-saas/deployments
FieldTypeRequiredDescription
namespacestringYesK8s-safe name (1–255 chars)
namestringYesDeployment display name (1–255)
templateSlugstringYesTemplate identifier
resourceTierstringYeslightweight, standard, or pro
agentCountnumberNoNumber of agent replicas (≥0)
configSnapshotobjectYesValidated CloudConfig
envVarsobjectNoKey-value environment overrides
runtimeContextobjectNo{ locale?, timezone? }

Creates a new deployment with billing. Validates the template, locks the namespace, and checks wallet balance (returns 402 if insufficient). The deployment is queued asynchronously.

Get deployment

GET /api/cloud-saas/deployments/:id

Returns full deployment detail including current status, blocking info, and cost summary.

Get deployment costs

GET /api/cloud-saas/deployments/:id/costs

Returns cost summary for a specific deployment.

Cancel deployment

POST /api/cloud-saas/deployments/:id/cancel

Cancels an active deploy or destroy task. Does not wait for namespace operation locks.

Delete deployment

DELETE /api/cloud-saas/deployments/:id

Queues a Pulumi destroy for the current deployment entry. Interrupts active operations.

Redeploy

POST /api/cloud-saas/deployments/:id/redeploy
FieldTypeRequiredDescription
modestringNosnapshot (default) or template
templateSlugstringNoRedeploy from a specific template
configSnapshotobjectNoExplicit config after policy validation
envVarsobjectNoOverride declared template env vars
runtimeContextobjectNo{ locale?, timezone? }

Re-enqueues the same namespace with a new deployment history entry. Does not debit wallet.


Deployment logs

GET /api/cloud-saas/deployments/:id/logs GET /api/cloud-saas/deployments/:id/logs/history
QueryTypeDescription
agentstringFilter by agent name
podstringFilter by pod name
pagenumberPage (1–100)
limitnumberPer page (20–500, default 200)

GET /logs returns an SSE event stream (text/event-stream) with real-time events: log, status, error, close. Terminates when deployment reaches terminal status.

GET /logs/history returns a plain JSON array of log entries.

Pod info

GET /api/cloud-saas/deployments/:id/pods GET /api/cloud-saas/deployments/:id/pod-logs
QueryTypeDescription
podstringPod name (required for pod-logs)
agentstringAgent name
tailnumberLines to tail (default 200, max 2000)
containerstringContainer name (default 'openclaw')

GET /pods lists K8s pods in the deployment namespace. GET /pod-logs streams live K8s pod logs via SSE.

Orphan management

POST /api/cloud-saas/deployments/orphans/:namespace/claim POST /api/cloud-saas/deployments/orphans/:namespace/cleanup

/claim adopts a Shadow-Cloud-managed namespace with no DB row. /cleanup force-deletes an orphan namespace (admin only).


Environment Variables

Deployment-scoped env vars

GET /api/cloud-saas/envvars/:deploymentId GET /api/cloud-saas/envvars/:deploymentId/:key PUT /api/cloud-saas/envvars/:deploymentId DELETE /api/cloud-saas/envvars/:deploymentId/:key
FieldTypeRequiredDescription
varsarrayYes (PUT)[{ key: string, value: string }]

Values are encrypted at rest. GET returns masked values ('****'). GET by key returns decrypted value for editing.

Global env vars

GET /api/cloud-saas/global-envvars GET /api/cloud-saas/global-envvars/:key PUT /api/cloud-saas/global-envvars DELETE /api/cloud-saas/global-envvars/:key
FieldTypeRequiredDescription
keystringYesVariable key
valuestringYesVariable value
isSecretbooleanNoWhether to treat as secret (masked)
groupNamestringNoOptional grouping

Global env var groups

POST /api/cloud-saas/global-envvars/groups DELETE /api/cloud-saas/global-envvars/groups/:name
FieldTypeRequiredDescription
namestringYesGroup name (1–255 chars)

Provider Profiles & Catalogs

List provider catalogs

GET /api/cloud-saas/provider-catalogs

Returns model providers discovered from installed Cloud plugins. Each entry includes plugin ID, provider details, and required secret fields.

List provider profiles

GET /api/cloud-saas/provider-profiles

Returns the current user's encrypted provider profiles. Values are masked.

Upsert provider profile

PUT /api/cloud-saas/provider-profiles
FieldTypeRequiredDescription
idstringNoProfile ID (for updates)
providerIdstringYesCatalog provider ID (1–120 chars)
namestringYesDisplay name (1–255)
enabledbooleanNoWhether the profile is active
configobjectNoProvider-specific config
envVarsobjectNoEncrypted env var values

Validates model list in config and applies SSRF guard on any base URL.

Test provider profile

POST /api/cloud-saas/provider-profiles/:id/test

Tests encrypted credentials against the provider API with 8s timeout and SSRF protection.

Refresh models

POST /api/cloud-saas/provider-profiles/:id/models/refresh

Fetches model list from the provider's native API and persists into the profile config.

Delete provider profile

DELETE /api/cloud-saas/provider-profiles/:id

Deletes the profile and all associated encrypted values.


Wallet

Get balance

GET /api/cloud-saas/wallet

Returns the current user's Shrimp Coin balance.

Response:

{
  "balance": 5000,
  "currency": "shrimp_coin"
}

Transaction history

GET /api/cloud-saas/wallet/transactions
QueryTypeDescription
limitnumberMax results (50 default, 100 max)
offsetnumberPagination offset (0 default)

Returns paginated wallet transaction history.


Activity Log

GET /api/cloud-saas/activity
QueryTypeDescription
limitnumberMax results (50 default, 100 max)
offsetnumberPagination offset (0 default)

Returns the user's cloud activity log (paginated), including deployment creation, pause, resume, backup, restore, and deletion events.


DIY Cloud (AI Generation)

Create generation run

POST /api/cloud-saas/diy/runs
FieldTypeRequiredDescription
promptstringYesGeneration prompt (4–2000 chars)
feedbackstringNoFollow-up feedback (≤2000)
previousConfigobjectNoPrevious CloudConfig for iteration
localestringNoUser locale (≤16 chars)
timezonestringNoUser timezone (≤64 chars)

Rate-limited to 12 requests per minute. Returns runId, status, and streamUrl.

AI generation requires capability checks, rate/budget controls, and token estimates before model calls.

Get run

GET /api/cloud-saas/diy/runs/:runId GET /api/cloud-saas/diy/runs/:runId/stream
QueryTypeDescription
afterSeqnumberEvent sequence offset (≥0)

GET /runs/:runId returns the run with events after afterSeq. GET /stream provides an SSE event stream (text/event-stream) for real-time progress.

Follow-up run

POST /api/cloud-saas/diy/runs/:runId/feedback
FieldTypeRequiredDescription
feedbackstringYesRefinement feedback (1–2000)
promptstringNoUpdated prompt (4–2000)
localestringNoUser locale
timezonestringNoUser timezone

Cancel run

POST /api/cloud-saas/diy/runs/:runId/cancel

Cancels a running generation. No body required.

DIY resources

GET /api/cloud-saas/diy/templates GET /api/cloud-saas/diy/plugins GET /api/cloud-saas/diy/plugins/search?q=...

Rate-limited endpoints that list available community templates and plugins for use in DIY generation.


Schema & Validation

GET /api/cloud-saas/schema POST /api/cloud-saas/validate

GET /schema returns the primary CloudConfig JSON Schema for frontend validation and editor autocomplete.

POST /validate accepts a raw JSON config snapshot and returns a validation summary with errors.


Client Methods

// Templates
const { templates } = await client.listCloudTemplates({ q: 'web' })
const template = await client.getCloudTemplate('web-app')

// Deployments
const { deployments } = await client.listCloudDeployments()
const deployment = await client.createCloudDeployment({
  namespace: 'my-app',
  name: 'My App',
  templateSlug: 'web-app',
  resourceTier: 'standard',
  configSnapshot: {},
})
await client.redeployCloudDeployment(deployment.id, { mode: 'template' })
await client.cancelCloudDeployment(deployment.id)

// Deployment lifecycle
await client.pauseCloudDeployment('dep-id', { agentId: 'agent-name' })
await client.resumeCloudDeployment('dep-id')

// Backups
const { backups } = await client.listCloudDeploymentBackups('dep-id')
const { backup } = await client.createCloudDeploymentBackup('dep-id', { driver: 'volumeSnapshot' })
await client.restoreCloudDeploymentBackup('dep-id', { backupId: 'backup-id' })

// Manifest & template sync
const manifest = await client.getCloudDeploymentManifest('dep-id')
await client.syncCloudDeploymentTemplate('dep-id', { name: 'My Fork' })

// Provider profiles
const catalogs = await client.listCloudProviderCatalogs()
const profiles = await client.listCloudProviderProfiles()
await client.upsertCloudProviderProfile({ providerId: 'openai', name: 'My Key', config: {} })
await client.testCloudProviderProfile('profile-id')
await client.deleteCloudProviderProfile('profile-id')

// Wallet
const wallet = await client.getWallet()
const { transactions } = await client.getWalletTransactions()

// DIY generation
const { runId } = await client.createDiyCloudRun({ prompt: 'Create a chatbot' })
const run = await client.getDiyCloudRun(runId)
await client.createDiyCloudFeedbackRun(runId, { feedback: 'Add dark mode' })
await client.cancelDiyCloudRun(runId)
# Templates
result = client.list_cloud_templates(q="web")
template = client.get_cloud_template("web-app")

# Deployments
result = client.list_cloud_deployments()
deployment = client.create_cloud_deployment(
    namespace="my-app",
    name="My App",
    template_slug="web-app",
    resource_tier="standard",
    config_snapshot={},
)
client.redeploy_cloud_deployment(deployment["id"], mode="template")
client.cancel_cloud_deployment(deployment["id"])

# Deployment lifecycle
client.pause_cloud_deployment("dep-id", agent_id="agent-name")
client.resume_cloud_deployment("dep-id")

# Backups
result = client.list_cloud_deployment_backups("dep-id")
result = client.create_cloud_deployment_backup("dep-id", driver="volumeSnapshot")
client.restore_cloud_deployment_backup("dep-id", backup_id="backup-id")

# Manifest & template sync
manifest = client.get_cloud_deployment_manifest("dep-id")
client.sync_cloud_deployment_template("dep-id", name="My Fork")

# Provider profiles
catalogs = client.list_cloud_provider_catalogs()
profiles = client.list_cloud_provider_profiles()
client.upsert_cloud_provider_profile(provider_id="openai", name="My Key", config={})
client.test_cloud_provider_profile("profile-id")
client.delete_cloud_provider_profile("profile-id")

# Wallet
wallet = client.get_wallet()
result = client.get_wallet_transactions()

# DIY generation
result = client.create_diy_cloud_run(prompt="Create a chatbot")
run = client.get_diy_cloud_run(result["run_id"])
client.create_diy_cloud_feedback_run(result["run_id"], feedback="Add dark mode")
client.cancel_diy_cloud_run(result["run_id"])

Next Steps