Management API
Automate Clouzark over HTTP.
The CLI and MCP server are built on this API; anything they do, you can do with plain HTTP.
https://api.clouzark.com/v1Authentication
Send a team access token, created under the team's Settings → Access Tokens (or by clouzark login):
curl https://api.clouzark.com/v1/me -H "Authorization: Bearer cz_pat_..."A token acts with its creator's current role in the team. Requests and responses are JSON, errors are { "error": "..." }, and each token can make 120 requests a minute. Wherever a path has :ref, pass a project's slug or id.
Account
| Request | |
|---|---|
GET /me | User, team, role, and token expiry |
DELETE /tokens/current | Revoke the calling token |
Hosting projects
| Request | |
|---|---|
GET /projects | List projects |
GET /projects/:ref | One project, including runtime_memory_mb (its instance size, null for the platform default) and the resulting runtime_limits |
PATCH /projects/:ref { runtime_memory_mb } | Set the instance size: 512, 1024, 2048, 4096, or null. Owner role. Returns { project, runtime_limits_applied: { updated, skipped } } |
POST /projects { repo, name?, root_directory?, framework?, production_branch?, install_command?, build_command?, output_directory?, env_vars? } | Import a GitHub repo (owner/name) and queue its first production build; returns { project, deployment_id }. env_vars ([{ key, value, target }]) are saved before that build |
GET /projects/:ref/deployments?limit=20 | Recent deployments |
POST /projects/:ref/deployments { branch?, skip_build_cache? } | Build a branch's latest pushed commit (the production branch by default) |
POST /projects/:ref/deployments/upload?environment=preview&skip_build_cache=false | Build an uploaded .tar.gz of the project (Content-Type: application/gzip) |
POST /projects/:ref/rollback | Roll production back |
POST /projects/:ref/repository/sync | Re-read the repo from GitHub and follow a rename or transfer to its current URL. A project ref (and app URL) made from the old repo name moves to one made from the new name, and the old app URL redirects to it. Deployer role. Returns { project, changed, previous_repo_url, previous_ref, previous_url } |
GET /deployments/:id?log_offset=0 | Deployment status, plus build log from log_offset |
POST /deployments/:id/promote | Promote to production |
POST /deployments/:id/redeploy { skip_build_cache? } | Rebuild; skip_build_cache: true builds without the build cache |
POST /deployments/:id/cancel | Cancel a queued deployment |
Each deployment has a url (its own immutable URL) and, for a preview, a branch_url that always serves the branch's newest live deployment.
A deployment's status is one of queued, building, deploying, live, failed, canceled, or stopped; done is true once it stops changing. To follow a build, poll GET /deployments/:id and pass the previous log_length as log_offset.
Environment variables
| Request | |
|---|---|
GET /projects/:ref/env | Names, targets, and git_branch |
GET /projects/:ref/env/values?environment=preview&branch=dev | Resolved values for one environment (and, for preview, one branch) |
POST /projects/:ref/env { key, value, target, git_branch? } | Add or update. git_branch only with target: preview |
PATCH /projects/:ref/env/:key?target=preview&git_branch=dev { value } | Change only the value |
DELETE /projects/:ref/env/:key?target=all&git_branch= | Remove |
GET /projects/:ref/database | The linked database ({ database: { id, name, ref } | null, env_keys }) |
PATCH /projects/:ref/database { database } | Link a database by ref or id, or unlink with null; needs the deployer role. Applies from the next deployment |
Domains
| Request | |
|---|---|
GET /projects/:ref/domains | Domains, with the DNS records each needs |
POST /projects/:ref/domains { hostname, routing? } | Add, optionally with a routing choice (below) |
PATCH /projects/:ref/domains/:hostname { mode, target_branch?, redirect_to?, redirect_status? } | Change what it serves: production, preview, branch (with target_branch), or redirect |
POST /projects/:ref/domains/:hostname/verify | Check DNS |
DELETE /projects/:ref/domains/:hostname | Remove |
App cron jobs
Cron jobs are addressed by :job, the job's name or id. Creating, changing, deleting, and running jobs needs the deployer role. A job with source: "config" comes from clouzark.json: it only accepts enabled, and can't be deleted.
| Request | |
|---|---|
GET /projects/:ref/cron-jobs | Jobs, each with source (config or api), next_run_at, and last_run |
GET /projects/:ref/cron-jobs/:job | One job |
POST /projects/:ref/cron-jobs { name, path, schedule, method?, timezone?, timeout_seconds?, retries?, enabled? } | Add a job. method defaults to GET, timezone to UTC, timeout_seconds to 60 (at most 300), retries to 0 (at most 3). Returns { cron_job } |
PATCH /projects/:ref/cron-jobs/:job { name?, path?, schedule?, method?, timezone?, timeout_seconds?, retries?, enabled? } | Change only the fields sent; enabled: false pauses the job |
DELETE /projects/:ref/cron-jobs/:job | Delete the job and its runs |
POST /projects/:ref/cron-jobs/:job/run | Call the path now and wait; returns { run: { id, status, status_code, attempts, duration_ms, message } } |
GET /projects/:ref/cron-jobs/:job/runs?limit=20 | Recent runs, newest first |
Database projects
| Request | |
|---|---|
GET /database-projects | List databases |
GET /database-projects/:ref | One database |
POST /database-projects { name } | Create |
DELETE /database-projects/:ref | Delete permanently |
POST /database-projects/:ref/query { sql, read_only? } | Run SQL; returns { command, row_count, fields, rows, duration_ms } |
GET /database-projects/:ref/migrations | Applied migrations |
POST /database-projects/:ref/migrations { version, name, sql } | Apply a migration. version is YYYYMMDDHHMMSS; re-sending the same SQL is a no-op, different SQL for an applied version is a 409 |
GET /database-projects/:ref/types/typescript?schemas=public,career | { types }; schemas defaults to public, and an unknown schema returns 404 with available_schemas |
GET /database-projects/:ref/keys | { rest_url, anon_key, service_key } |
GET /database-projects/:ref/credentials | Host, port, database, username, password, connection_string (direct), and pooled_connection_string (the connection pooler; null if unavailable) |
Database cron jobs
Cron jobs are addressed by :job, the job's name or id. Creating, changing, deleting, and running jobs needs the deployer role.
| Request | |
|---|---|
GET /database-projects/:ref/cron-jobs | Jobs, each with next_run_at and last_run |
GET /database-projects/:ref/cron-jobs/:job | One job |
POST /database-projects/:ref/cron-jobs { name, schedule, command, timezone?, timeout_seconds?, enabled? } | Add a job. schedule is 5-field cron; timezone defaults to UTC, timeout_seconds to 60 (at most 300). Returns { cron_job } |
PATCH /database-projects/:ref/cron-jobs/:job { name?, schedule?, command?, timezone?, timeout_seconds?, enabled? } | Change only the fields sent; enabled: false pauses the job |
DELETE /database-projects/:ref/cron-jobs/:job | Delete the job and its runs |
POST /database-projects/:ref/cron-jobs/:job/run | Run now and wait; returns { run: { id, status, duration_ms, message } } |
GET /database-projects/:ref/cron-jobs/:job/runs?limit=20 | Recent runs, newest first |
Database backups
Backups are addressed by :id. Taking or downloading one needs the deployer role; restoring needs the owner role.
| Request | Does |
|---|---|
GET /database-projects/:ref/backups | { enabled, retention_days, backups, restores }, newest first. Each backup has kind (scheduled, manual, pre_restore), status, and size_bytes |
POST /database-projects/:ref/backups | Back up now and wait; returns { backup } (201, or 500 with the error if it failed) |
GET /database-projects/:ref/backups/:id/download | { url }: a download link valid for 15 minutes |
POST /database-projects/:ref/backups/:id/restore | Start a restore (202, { restore }). Poll GET .../backups until that restore's status is succeeded or failed |
Import from Supabase
The Supabase credentials are used for that request or import only and never stored. Needs the deployer role.
| Request | Does |
|---|---|
POST /import/supabase/inspect { connection_string, supabase_url?, service_key? } | Dry run: { report } with schemas, counts, warnings, and what won't carry over |
POST /import/supabase { name, connection_string, supabase_url?, service_key? } | Create a database and start importing into it (202, { import_id }) |
GET /imports/:id | { import: { status, step, report, error, database_ref } }; poll until status is succeeded or failed |