Public API
The Public API lets you manage projects, web services, deployments and managed databases programmatically from CI pipelines, CLIs or any HTTP client. It is the only externally supported HTTP surface of the platform.
The base URL is https://api.runsite.app.
Authentication
Section titled “Authentication”Every request must include an API key in the Authorization header:
Authorization: Bearer ak_live_a1b2c3d4...Create and manage keys from the dashboard; see API Keys. Requests without a valid, active key get 401 Unauthorized.
Describe the presented key
Section titled “Describe the presented key”GET /api/v1/users/me/api-keyReturns the key’s id, name, key_prefix, scope and expiry, never the key
itself. Use it to discover what a key is allowed to do before calling a
write endpoint.
Projects
Section titled “Projects”List projects
Section titled “List projects”GET /api/v1/projectsReturns all projects owned by the authenticated user.
Create a project
Section titled “Create a project”POST /api/v1/projectsContent-Type: application/json
{ "name": "my-app", "description": "My application"}Get project details
Section titled “Get project details”GET /api/v1/projects/{project_id}Web Services
Section titled “Web Services”List web services
Section titled “List web services”GET /api/v1/web-servicesCreate a web service
Section titled “Create a web service”POST /api/v1/web-servicesContent-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 a web service
Section titled “Get a web service”GET /api/v1/web-services/{web_service_id}Deploy / Start / Restart / Stop
Section titled “Deploy / Start / Restart / Stop”POST /api/v1/web-services/{web_service_id}/deployPOST /api/v1/web-services/{web_service_id}/startPOST /api/v1/web-services/{web_service_id}/restartPOST /api/v1/web-services/{web_service_id}/stopdeploy and start are the same action: they start the existing image and do
not rebuild. To build and release a new commit, create a deployment:
POST /api/v1/web-services/{web_service_id}/deploymentswhich returns the new deployment, including the id to poll with
GET /api/v1/web-services/{web_service_id}/deployments/{deployment_id}.
restart re-rolls existing instances without rebuilding. stop releases compute
(env vars and disks are preserved).
These four actions return the service’s lifecycle status (starting,
stopping, restarting) and refuse a service blocked by the content policy or
suspended for bandwidth.
Get container logs
Section titled “Get container logs”GET /api/v1/web-services/{web_service_id}/logs?tail=100&since=1710000000| Parameter | Type | Default | Description |
|---|---|---|---|
tail | int | 100 | Number of log lines (1–10000) |
since | int | none | Unix timestamp to filter logs from |
Get current metrics
Section titled “Get current metrics”GET /api/v1/web-services/{web_service_id}/metricsReturns CPU (millicores and percent of limit), memory (bytes and percent of
limit) and the running instance count. Responds 404 when the service is not
running and has no metrics to report.
Get metrics history
Section titled “Get metrics history”GET /api/v1/web-services/{web_service_id}/metrics/history?period=3600| Parameter | Type | Default | Description |
|---|---|---|---|
period | int | 3600 | Window in seconds, from 60 to 604800 (7 days) |
Per-service request rate and latency are not collected and are not available through this API.
Deployments
Section titled “Deployments”List deployments
Section titled “List deployments”GET /api/v1/web-services/{web_service_id}/deployments?limit=10&offset=0| Parameter | Type | Default | Description |
|---|---|---|---|
limit | int | 10 | Results per page (1–100) |
offset | int | 0 | Pagination offset |
Trigger a deployment
Section titled “Trigger a deployment”POST /api/v1/web-services/{web_service_id}/deploymentsContent-Type: application/json
{ "branch": "main"}The branch field is optional and defaults to the service’s configured branch.
Get deployment details
Section titled “Get deployment details”GET /api/v1/web-services/{web_service_id}/deployments/{deployment_id}Roll back to a previous deployment
Section titled “Roll back to a previous deployment”POST /api/v1/web-services/{web_service_id}/deployments/{deployment_id}/rollbackEnvironment Variables
Section titled “Environment Variables”List env vars
Section titled “List env vars”GET /api/v1/web-services/{web_service_id}/envValues of secret variables are masked in the response.
Create an env var
Section titled “Create an env var”POST /api/v1/web-services/{web_service_id}/envContent-Type: application/json
{ "key": "DATABASE_URL", "value": "postgres://...", "is_secret": true}Bulk replace env vars
Section titled “Bulk replace env vars”PUT /api/v1/web-services/{web_service_id}/env/bulkContent-Type: application/json
{ "variables": [ {"key": "NODE_ENV", "value": "production"}, {"key": "PORT", "value": "3000", "is_secret": false} ]}Delete an env var
Section titled “Delete an env var”DELETE /api/v1/web-services/{web_service_id}/env/{var_id}Project Secrets
Section titled “Project Secrets”Project secrets are scoped per environment (production, staging, development) and can be reused across services in the project.
List secrets
Section titled “List secrets”GET /api/v1/projects/{project_id}/secretsReturns secrets grouped by key.
Create a secret
Section titled “Create a secret”POST /api/v1/projects/{project_id}/secretsContent-Type: application/json
{ "key": "STRIPE_SECRET_KEY", "value": "sk_live_...", "scope": "production", "is_secret": true}| Scope | Description |
|---|---|
production | Used in production deployments |
staging | Used in staging environments |
development | Used in development environments |
Bulk replace secrets
Section titled “Bulk replace secrets”PUT /api/v1/projects/{project_id}/secrets/bulkContent-Type: application/json
{ "secrets": [ {"key": "API_SECRET", "value": "value1", "scope": "production"}, {"key": "API_SECRET", "value": "value2", "scope": "staging"} ]}Delete a secret
Section titled “Delete a secret”DELETE /api/v1/projects/{project_id}/secrets/{secret_id}List plans
Section titled “List plans”GET /api/v1/plans?service_type=postgresql| Parameter | Type | Description |
|---|---|---|
service_type | string | Required. web_service, postgresql or redis |
Returns the active plans for that service type with id, slug, monthly price
in cents and resource limits. Pass a plan’s id as plan_id when creating a
database.
Managed Databases
Section titled “Managed Databases”Connection URLs and credentials are never returned by any of these endpoints. To give a web service access to a database, create a connection: the URL is injected into the service as a secret environment variable on the server side.
List databases
Section titled “List databases”GET /api/v1/databases?limit=50&offset=0Returns Postgres and Valkey instances of the active workspace in one list, each
carrying kind, status, plan name, configured limits and hostnames.
Get a database
Section titled “Get a database”GET /api/v1/databases/{database_id}Same fields plus current CPU and memory usage when the instance is running.
Usage is collected for Postgres only; for Valkey those fields are null.
Every database endpoint is scoped to the caller’s active workspace.
Create a Postgres database
Section titled “Create a Postgres database”Needs a write key. Billed from the account balance.
POST /api/v1/databasesContent-Type: application/json
{ "name": "main-db", "plan_id": "uuid", "project_id": "uuid", "postgres_version": "16"}| Field | Required | Description |
|---|---|---|
name | yes | Display name, 1–100 characters |
plan_id | yes | A postgresql plan from List plans |
project_id | no | Needed to connect the database to a service of that project |
postgres_version | no | 14, 15, 16 (default) or 17 |
storage_gb | no | Extra GB on top of the plan’s storage, 0–1000, billed per GB |
The database name, user and password are generated on the server. The response
is the new database with status creating; provisioning takes a minute or two,
so poll Get a database until it is running.
Create a Valkey (Redis) instance
Section titled “Create a Valkey (Redis) instance”Needs a write key. Billed from the account balance.
POST /api/v1/redisContent-Type: application/json
{ "name": "cache", "plan_id": "uuid", "project_id": "uuid"}Takes the same fields as the Postgres endpoint, except that the version field is
redis_version (7.2 by default, or 8.0). The ACL user and password are
generated on the server.
Both create endpoints allow 5 requests per minute per key.
Start / Stop
Section titled “Start / Stop”Needs a write key.
POST /api/v1/databases/{database_id}/startPOST /api/v1/databases/{database_id}/stopWorks for both engines; the id decides which one. Stopping keeps the data and
the plan, but services connected to the database lose their connection until it
is started again. The response carries the database id, kind and new
status.
Delete a database
Section titled “Delete a database”Needs an admin key.
DELETE /api/v1/databases/{database_id}Deletes a Postgres or Valkey instance together with all of its data, and
returns 204. There is no undo, so back up anything you need first.
Connect a database to a web service
Section titled “Connect a database to a web service”Needs a write key.
POST /api/v1/web-services/{web_service_id}/connectionsContent-Type: application/json
{ "target_type": "database", "target_id": "uuid"}target_type is database for Postgres and redis for Valkey. The service and
the database must belong to the same project. Runsite sets DATABASE_URL or
REDIS_URL on the service as a secret environment variable; the response names
the variable in env_var_key but never includes its value. Deploy or restart
the service so the running process picks it up.
Error Responses
Section titled “Error Responses”All errors follow a consistent format:
{ "detail": "Error message describing what went wrong"}| Status | Description |
|---|---|
400 | Bad request: invalid input |
401 | Unauthorized: invalid or missing credentials |
403 | Forbidden: insufficient scope |
404 | Resource not found |
429 | Rate limit exceeded |
A 403 raised by the scope check carries a structured detail rather than a
string, so a client can tell the caller which scope the key is missing:
{ "detail": { "code": "insufficient_scope", "required": "write", "actual": "read" }}429 means the public API rate limit (30 requests per minute) was exceeded. The
budget is per API key, so two keys never share one bucket.
Try it interactively
Section titled “Try it interactively”Browse and call the API live in the API Explorer.