Skip to content

Public API

The Public API lets you manage projects, web services, static sites, deployments, managed databases, object storage and email programmatically — using API keys or JWT tokens.

Include your API key or JWT token in the Authorization header:

Terminal window
# API key
Authorization: Bearer ak_live_a1b2c3d4...
# JWT token
Authorization: Bearer <access_token>

All endpoints return 401 Unauthorized if the key is invalid, expired, or missing.


GET /api/projects

Returns all projects owned by the authenticated user.

POST /api/projects
Content-Type: application/json
{
"name": "my-app",
"description": "My application"
}
GET /api/projects/{project_id}

GET /api/web-services
POST /api/web-services
Content-Type: application/json
{
"name": "backend-api",
"project_id": "uuid",
"git_repository_url": "https://github.com/user/repo",
"port": 3000,
"build_command": "npm run build",
"min_instances": 1,
"max_instances": 3
}
GET /api/web-services/{web_service_id}
PATCH /api/web-services/{web_service_id}
Content-Type: application/json
{
"name": "new-name",
"min_instances": 2
}
DELETE /api/web-services/{web_service_id}
POST /api/web-services/{web_service_id}/start
POST /api/web-services/{web_service_id}/stop
POST /api/web-services/{web_service_id}/restart
GET /api/web-services/{web_service_id}/logs?tail=100&since=1710000000
ParameterTypeDefaultDescription
tailint100Number of log lines (1–10000)
sinceintUnix timestamp to filter logs from

GET /api/web-services/{web_service_id}/deployments?limit=10&offset=0
ParameterTypeDefaultDescription
limitint10Results per page (1–100)
offsetint0Pagination offset
POST /api/web-services/{web_service_id}/deployments
Content-Type: application/json
{
"branch": "main"
}

The branch field is optional — defaults to the service’s configured branch.

GET /api/web-services/{web_service_id}/deployments/{deployment_id}
POST /api/web-services/{web_service_id}/deployments/{deployment_id}/cancel
POST /api/web-services/{web_service_id}/deployments/{deployment_id}/rollback

GET /api/web-services/{web_service_id}/env

Values of secret variables are masked. Use the reveal endpoints to see full values.

GET /api/web-services/{web_service_id}/env/reveal-all
GET /api/web-services/{web_service_id}/env/{var_id}/reveal
POST /api/web-services/{web_service_id}/env
Content-Type: application/json
{
"key": "DATABASE_URL",
"value": "postgres://...",
"is_secret": true
}
PATCH /api/web-services/{web_service_id}/env/{var_id}
Content-Type: application/json
{
"value": "new-value"
}
PUT /api/web-services/{web_service_id}/env/bulk
Content-Type: application/json
{
"variables": [
{"key": "NODE_ENV", "value": "production"},
{"key": "PORT", "value": "3000", "is_secret": false}
]
}
DELETE /api/web-services/{web_service_id}/env/{var_id}

Secrets are scoped per environment (production, staging, development) with a fallback chain. They can be bound to web services via secret bindings.

GET /api/projects/{project_id}/secrets
POST /api/projects/{project_id}/secrets
Content-Type: application/json
{
"key": "STRIPE_SECRET_KEY",
"value": "sk_live_...",
"scope": "production",
"is_secret": true
}
ScopeDescription
productionUsed in production deployments
stagingUsed in staging environments
developmentUsed in development environments
GET /api/projects/{project_id}/secrets/{secret_id}/reveal
PATCH /api/projects/{project_id}/secrets/{secret_id}
Content-Type: application/json
{
"value": "new-value"
}
PUT /api/projects/{project_id}/secrets/bulk
Content-Type: application/json
{
"secrets": [
{"key": "API_SECRET", "value": "value1", "scope": "production"},
{"key": "API_SECRET", "value": "value2", "scope": "staging"}
]
}
DELETE /api/projects/{project_id}/secrets/{secret_id}

Secret bindings map project secrets to web service environment variables.

GET /api/web-services/{web_service_id}/secret-bindings
POST /api/web-services/{web_service_id}/secret-bindings
Content-Type: application/json
{
"project_secret_id": "uuid",
"alias_key": "DB_PASSWORD"
}
GET /api/web-services/{web_service_id}/secret-bindings/resolved

Returns the merged view of environment variables and bound secrets, showing the final values that will be injected into the service.

PUT /api/web-services/{web_service_id}/secret-bindings/bulk
Content-Type: application/json
{
"bindings": [
{"project_secret_id": "uuid", "alias_key": "DB_PASSWORD"},
{"project_secret_id": "uuid", "alias_key": "REDIS_URL"}
]
}
DELETE /api/web-services/{web_service_id}/secret-bindings/{binding_id}

POST /api/databases # Create
GET /api/databases # List all
GET /api/databases/{database_id} # Get details
PATCH /api/databases/{database_id} # Update
DELETE /api/databases/{database_id} # Delete
POST /api/databases/{database_id}/start # Start
POST /api/databases/{database_id}/stop # Stop
GET /api/databases/{database_id}/status # Status
POST /api/redis # Create
GET /api/redis # List all
GET /api/redis/{redis_id} # Get details
PATCH /api/redis/{redis_id} # Update
DELETE /api/redis/{redis_id} # Delete
POST /api/redis/{redis_id}/start # Start
POST /api/redis/{redis_id}/stop # Stop
GET /api/redis/{redis_id}/status # Status

GET /api/storage/tenant # Tenant quota / limits
POST /api/storage/buckets # Create bucket
GET /api/storage/buckets # List buckets
PATCH /api/storage/buckets/{bucket_id} # Update
DELETE /api/storage/buckets/{bucket_id} # Delete
POST /api/storage/keys # Create access key
GET /api/storage/keys # List keys
DELETE /api/storage/keys/{key_id} # Revoke key
POST /api/storage/buckets/{bucket_id}/presign # Presigned URL

See Object Storage for full details.


GET /api/email/tenant # Tenant info
POST /api/email/services # Create service
GET /api/email/services # List services
PATCH /api/email/services/{service_id} # Update
DELETE /api/email/services/{service_id} # Delete
POST /api/email/services/{service_id}/api-keys # Create API key
GET /api/email/services/{service_id}/api-keys # List keys
POST /api/email/services/{service_id}/domains # Add sending domain
GET /api/email/services/{service_id}/domains # List domains
POST /api/email/services/{service_id}/sandbox-emails # Verify recipient
POST /api/email/services/{service_id}/send # Send email
GET /api/email/services/{service_id}/stats # Stats
POST /api/email/services/{service_id}/webhooks # Create webhook

See Email for full details.


All errors follow a consistent format:

{
"detail": "Error message describing what went wrong"
}
StatusDescription
400Bad request — invalid input
401Unauthorized — invalid or missing credentials
403Forbidden — insufficient scope
404Resource not found
429Rate limit exceeded