Voxen Cloud · API + CLI

Documentation

Every endpoint, every CLI command, with copy-paste examples. All authenticated requests use Authorization: Bearer <token>. Base URL: https://voxenlabs.cloud.

#Quickstart

Three ways to use Voxen, in order of how fast you want to be productive.

#1. The dashboard (no install)

Sign up at voxenlabs.cloud/signup, hit "Create project," edit files in the browser IDE, click "Deploy." That's the whole loop.

#2. The CLI

curl -fsSL https://voxenlabs.cloud/install.sh | sh
vox login                    # paste a token from /dashboard/tokens
vox init my-app              # writes voxen.toml
vox deploy                   # zip + upload + live

#3. The HTTP API

Anything the CLI does is one HTTP request. Get a token from /dashboard/tokens, then:

# List your projects
curl https://voxenlabs.cloud/api/projects \
  -H "Authorization: Bearer voxen_xxxxxxxxxx"

#Authentication

Two auth modes. Browser sessions use a JWT in Authorization: Bearer <jwt> (or an httpOnly cookie); scripts use long-lived API tokens that start with voxen_.

#API tokens

Create at /dashboard/tokens, or with the CLI:

vox tokens create "ci-deploy" \
  --scopes deploys:write,files:write \
  --expires-in-days 90

# → voxen_a1b2c3d4...

The token is shown once. Lose it, revoke and create a new one.

#Scopes

Scope a token to limit blast radius. A token with no scopes selected is unrestricted.

ScopeAllows
projects:readList projects, view settings
projects:writeCreate / update / delete projects
deploys:writeTrigger builds and publish
files:readRead draft files + manifests
files:writePush, pull, edit, delete files
service:controlStart / stop / restart / scale
db:readList DBs + connection strings
db:writeCreate / scale / delete DBs, backups
functions:readRead function code + metadata
functions:writeCreate / update / delete functions
billing:readBalance, usage, transactions
adminAll scopes

#Two-factor auth

Optional TOTP on user accounts. Enable from Settings → Two-factor authentication. Browser logins prompt for a 6-digit code; backup codes are issued at enrollment and consumed on use. API tokens are not gated by 2FA — the gate is when you create the token in the dashboard.

#Projects

A project is a slug, a kind (STATIC · HOSTED · DOCKER · SERVICE), and resources.

GET/api/projectsscope: projects:read

List your projects.

{ "projects": [{ "id": "cmp...", "name": "Astrid", "slug": "astrid", "kind": "HOSTED", "serviceStatus": "LIVE", ... }] }
POST/api/projectsscope: projects:write

Create a project.

{
  "name": "Astrid",
  "slug": "astrid",              // 1-8 chars = premium tier, 9+ = free
  "kind": "HOSTED",
  "paymentMethod": "credits"     // required only if slug is premium
}
GET/api/projects/[id]scope: projects:read
PATCH/api/projects/[id]scope: projects:write

Update settings, resources, scaling. All fields optional.

{
  "name": "new name",
  "customDomain": "astrid.dev",
  "passwordHash": "raw-password",     // hashed server-side
  "notFoundPath": "/404.html",
  "spaFallback": true,
  "redirects": [{ "from": "/old", "to": "https://...", "status": 301 }],
  "headers":   [{ "path": "/*", "name": "X-Frame-Options", "value": "DENY" }],
  "memoryMb": 1024,                   // 128 → 16384, hot-swap
  "cpuMillicores": 1000,              // 100 → 8000, hot-swap
  "storageMb": 10240,                 // requires rebuild
  "replicas": 3,                      // requires rebuild
  "autoSleepMinutes": 15              // 0 = always on
}
DELETE/api/projects/[id]scope: projects:write

#Files & drafts

Edits land in a draft workspace. Nothing goes live until you publish.

GET/api/projects/[id]/files/manifestscope: files:read

List every file in the draft with SHA-256 hashes. Powers vox pull / vox push diffing.

{ "files": [{ "path": "/index.html", "bytes": 4231, "sha256": "..." }] }
GET/api/projects/[id]/files/content?path=/index.htmlscope: files:read
PUT/api/projects/[id]/files/content?path=/index.htmlscope: files:write
{ "content": "<html>...</html>" }
DELETE/api/projects/[id]/files/content?path=/old.htmlscope: files:write
POST/api/projects/[id]/draftscope: deploys:write

Publish or discard the draft.

{ "action": "publish" }     // or "discard"

#Deploys

For static projects you can also skip the draft and upload a zip directly.

POST/api/deploysscope: deploys:write

Multipart form: zip=<file.zip>, projectId=....

curl -F "zip=@./dist.zip" -F "projectId=cmp..." \
  -H "Authorization: Bearer voxen_..." \
  https://voxenlabs.cloud/api/deploys
GET/api/projects/[id]/deploysscope: projects:read
POST/api/projects/[id]/deploys/[did]scope: deploys:write

Roll back to a previous deploy.

DELETE/api/projects/[id]/deploys/[did]scope: deploys:write

Archive a deploy.

#Service control

For HOSTED / DOCKER / SERVICE projects.

POST/api/projects/[id]/service/controlscope: service:control
{ "action": "start" | "stop" | "restart" }
POST/api/projects/[id]/service/rebuildscope: service:control

Force-rebuild the active deploy without changing files.

GET/api/projects/[id]/service/logs?tail=Nscope: projects:read

#Env vars

Encrypted server-side. Injected at container start.

GET/api/projects/[id]/env?reveal=1scope: projects:read

reveal=1 decrypts values; without it, values come back as null.

PATCH/api/projects/[id]/envscope: projects:write
{
  "set":   { "STRIPE_KEY": "sk_live_xxx", "NODE_ENV": "production" },
  "unset": ["OLD_KEY"]
}

Reserved (auto-injected): PORT, VOXEN_PROJECT, VOXEN_REPLICA.

#Scaling

Memory and CPU hot-swap on running containers. Disk, replicas, and env changes need a restart/rebuild.

All scaling lives on PATCH /api/projects/[id] — see the projects table above.

#Pricing formula

compute_cents_per_hour =
    max(1,
        ceil(memoryMb / 256)        // 1¢ per 256 MB
      + ceil(cpuMillicores / 500)   // 1¢ per 0.5 vCPU
      + floor(storageMb / 10240)    // 1¢ per 10 GB disk
    )
  * replicas

# Example: 512 MB / 0.5 vCPU / 1 GB / 1 replica = 3¢/hr = $21.60/mo

#Custom domains

  1. Set customDomain via PATCH on the project.
  2. Add a CNAME pointing your domain at <slug>.voxenlabs.cloud.
  3. We auto-verify and issue Let's Encrypt TLS — usually within a minute.

Status flows: PENDING → VERIFYING → LIVE (or FAILED).

#Databases

Managed Postgres, MySQL, MariaDB, Redis.

GET/api/hosted-dbsscope: db:read
POST/api/hosted-dbsscope: db:write
{
  "name": "app-prod",
  "engine": "POSTGRES",   // POSTGRES | MYSQL | MARIADB | REDIS
  "paymentMethod": "credits"
}
GET/api/hosted-dbs/[id]scope: db:read

Returns { database, connectionString } if LIVE.

PATCH/api/hosted-dbs/[id]scope: db:write
{
  "name": "new-name",
  "memoryMb": 2048, "cpuMillicores": 1000,
  "storageMb": 51200,                      // only grow, requires restart
  "cacheMb": 512, "maxConns": 100,
  "backupSchedule": "daily",               // or "off"
  "backupRetentionDays": 14
}
POST/api/hosted-dbs/[id]/controlscope: db:write
{ "action": "start" | "stop" }
DELETE/api/hosted-dbs/[id]scope: db:write

#DB backups

GET/api/hosted-dbs/[id]/backupsscope: db:read
POST/api/hosted-dbs/[id]/backupsscope: db:write

Trigger a manual snapshot. Returns { backupId, status: "RUNNING" }. Poll the list to watch it flip to READY.

Scheduled (daily) backups run from a cron at the top of each hour and prune past the retention window.

#Functions

Single-file Node handlers invoked over HTTP. 1¢ per call.

GET/api/functionsscope: functions:read
POST/api/functionsscope: functions:write
{
  "name": "Webhook handler",
  "slug": "webhook",
  "code": "exports.handler = async (event) => ({ statusCode: 200, body: 'ok' });",
  "timeoutMs": 5000,
  "isPublic": true
}
GET/api/functions/[id]scope: functions:read
PATCH/api/functions/[id]scope: functions:write
DELETE/api/functions/[id]scope: functions:write

#Invoke

GET/api/fn/[slug]

Any HTTP method. Public unless isPublic=false, in which case the token must own the function.

curl -X POST https://voxenlabs.cloud/api/fn/webhook \
  -H "Content-Type: application/json" \
  -d '{"event":"order.created"}'

#Billing & usage

GET/api/credits?limit=Nscope: billing:read

Balance + recent transactions.

{ "balanceCents": 1240, "transactions": [
  { "amountCents": -3, "reason": "compute:cmp...:hourly", "metadata": {...}, "createdAt": "..." }
]}
GET/api/usagescope: billing:read

Live burn rate + MTD breakdown + per-resource spend.

POST/api/billing/topup

Returns a Stripe checkout URL for $1+ in credits.

{ "amountCents": 1000 }   // → { "url": "https://checkout.stripe.com/..." }

#Notifications & spend caps

GET/api/notifications
PATCH/api/notifications
{
  "notifyEmail": true,
  "lowBalanceCents": 500,       // email when balance < $5
  "softCapCents":    5000,      // email when MTD > $50
  "hardCapCents":   20000       // auto-stop services when MTD > $200
}

Set any to null to disable that threshold. Hourly cron checks; alerts debounce on 12-hour windows.

#AI chat

POST/api/projects/[id]/ai/chat

UI-message streaming response. Tools available to the model:

  • list_files, read_file, write_file, delete_file — edit the draft
  • web_search(query) — live web via Tavily
  • fetch_url(url) — pull arbitrary URLs (up to 50 KB)

Charged per token at inference cost + a thin margin.

#Errors

All errors are { "error": "human-readable message" } with an appropriate HTTP status.

StatusMeans
400Bad request — validation failed
401Missing or invalid token; for login, needsTotp: true if 2FA required
402Insufficient credit balance
403Token missing required scope, or non-owner
404Resource not found or not yours
500Something we did wrong — check status page

#CLI reference

Install:

curl -fsSL https://voxenlabs.cloud/install.sh | sh

#Projects

vox login                            # paste a token
vox init my-app --kind hosted        # writes voxen.toml
vox projects ls
vox projects create my-app --slug my-app --kind hosted
vox projects info my-app
vox projects use my-app              # set default in ~/.voxen/config.json
vox deploy                           # uses voxen.toml in cwd
vox publish                          # publish draft
vox status
vox open

#Files

vox push                             # local → draft (sha256 diff)
vox pull                             # draft → local
vox discard                          # throw away unpublished changes

#Service

vox scale --memory 2GB --cpu 1
vox scale --replicas 3 --sleep 15
vox scale --sleep off
vox restart | stop | start | rebuild
vox logs --tail 200
voxenv ls
voxenv set DATABASE_URL=postgres://...
voxenv unset OLD_KEY

#Databases

vox db ls
vox db create app-prod --engine postgres
vox db info <id>
vox db connstr <id>
vox db psql <id>                     # spawns local psql with conn string
vox db backups ls <id>
vox db backups run <id>
vox db backups schedule <id> --schedule daily --retain 14

#Functions, domains, tokens

vox fn ls | create | deploy <slug> <file.js> | invoke <slug> | rm
vox domains ls | add <host> --project <p> | rm
vox tokens create "ci" --scopes deploys:write --expires-in-days 30
vox tokens ls | rm <id>

#Settings / redirects / headers

vox settings                          # show
vox settings name "New Name"
vox settings not-found /404.html
vox settings spa on
vox settings password "secret"        # or "off"
vox redirects add /old https://new --status 301
vox headers add "/*" X-Frame-Options DENY

#Deploys & logs

vox deploys ls
vox deploys rollback <deploy-id>
vox build-logs                        # latest
vox tail                              # follow live logs

#Collaboration / GitHub

vox members add alice@x.com --role EDITOR
vox members role alice@x.com OWNER
vox members rm alice@x.com

vox github status
vox github link voxenlabs/my-app --branch main
vox github unlink

#2FA & notifications

vox 2fa setup                         # walks through QR + verify
vox 2fa disable

vox notifications                     # show
vox notifications set --low-balance 5 --soft-cap 50 --hard-cap 200

#Insights, slugs, branding

vox analytics --days 30
vox submissions                       # form submissions
vox slugs mine
vox slugs check axt
vox branding status
vox branding pay                      # one-time, removes footer

#Files & storage

vox files ls
vox files cat /index.html
vox files put /index.html ./build/index.html
vox files rm /old.html
vox files rename /old /new

vox storage ls                        # buckets
vox storage put <bucket> key ./file
vox storage get <bucket> key > file

#Starters & templates

vox starters ls
vox starters use nextjs-blog --name "My Blog"
vox templates deploy n8n --name "Automation"

#AI

vox ai "add a contact form to /contact.html"
vox ai-apply <message-id>             # accept proposal
vox ai-discard <message-id>           # reject

#Billing & Stripe Connect

vox balance
vox usage                             # full breakdown
vox topup 25
vox connect status                    # for taking payments on your sites
vox connect onboard

#voxen.toml

project = "astrid"
kind    = "hosted"

[deploy]
include = ["**/*"]
exclude = ["node_modules", ".git", ".next", "*.log", ".env*"]

[env]
NODE_ENV = "production"

Run any command from anywhere under the directory containing voxen.toml and it picks up the project automatically.