Applications
Managing apps, environments, env vars, source config, and custom domains.
An application is the top-level unit. It has a name, a namespace, and an auto-generated subdomain used for routing. Creating an app also creates production and development environments automatically.
POST /api/v1/apps — Create
Body
- name (string): Alphanumeric and hyphens
- namespace (string): Groups apps together (e.g.
production,staging) - description (string, optional)
- labels (object, optional): Arbitrary key-value metadata
curl -X POST http://localhost:47080/api/v1/apps \
-H 'Content-Type: application/json' \
-d '{"name":"my-api","namespace":"production","description":"Main API"}'// 201 Created
{
"id": "uuid",
"name": "my-api",
"namespace": "production",
"subdomain": "my-api-production",
"description": "Main API",
"labels": {},
"default_deployment_spec": null,
"created_at": "...",
"updated_at": "..."
}The subdomain is generated as {name}-{namespace} (non-alphanumeric → -). Returns 409 if the subdomain already exists.
GET /api/v1/apps — List
Query params
- namespace (string, optional): Filter by namespace
- page (number): Default
1 - page_size (number): Default
20, max100 - sort_by (string):
name,namespace,subdomain,created_at,updated_at - sort_order (string):
ascordesc
curl "http://localhost:47080/api/v1/apps?namespace=production&sort_by=name"{ "data": [ { ...app } ], "total": 42, "page": 1, "page_size": 20 }GET /api/v1/apps/
Fetch by UUID.
GET /api/v1/apps//
Fetch by human-readable key — useful when you know the name but not the UUID.
curl http://localhost:47080/api/v1/apps/production/my-apiGET /api/v1/apps/by-subdomain/
Fetch by subdomain. Used by the proxy for routing lookups.
PUT /api/v1/apps/ — Update
All fields are optional; omit to keep the current value.
Body
- description (string, optional)
- labels (object, optional)
- default_deployment_spec (object, optional): New deployments inherit these when the create payload doesn't specify them
- replicas (number)
- resources:
{ "cpu": "500m", "memory": "256Mi" } - max_runtime_secs (number or null)
curl -X PUT http://localhost:47080/api/v1/apps/$APP_ID \
-H 'Content-Type: application/json' \
-d '{"default_deployment_spec":{"replicas":2,"resources":{"cpu":"500m","memory":"256Mi"}}}'DELETE /api/v1/apps/
Stops all running tasks first, then deletes the app and its data. Returns 204 No Content.
Also available as DELETE /api/v1/apps/{namespace}/{name}.
Environments
Environments (production, development, or any custom slug) are created automatically when you create an app. They segment deployments and env vars.
GET /api/v1/apps//environments
[
{ "slug": "production", "description": "Live production deployment" },
{ "slug": "development", "description": "Latest deployment (main subdomain)" }
]Environment variables
Env vars are attached to an app and optionally scoped to an environment slug. When a deployment is created, vars for that environment plus unscoped vars are merged in — environment-specific vars win on conflict.
Keys are uppercased automatically. Setting the same key again overwrites it (upsert).
POST /api/v1/apps//env — Set a var
Body
- key (string): Alphanumeric and underscores only; auto-uppercased
- value (string)
- environment (string, optional): Scope to a specific environment. Omit or use
""to apply to all environments - is_secret (boolean, optional): Secret values are masked in list responses
# Applies to all environments
curl -X POST http://localhost:47080/api/v1/apps/$APP_ID/env \
-H 'Content-Type: application/json' \
-d '{"key":"LOG_LEVEL","value":"info"}'
# Production only
curl -X POST http://localhost:47080/api/v1/apps/$APP_ID/env \
-H 'Content-Type: application/json' \
-d '{"key":"DATABASE_URL","value":"postgres://...","environment":"production","is_secret":true}'GET /api/v1/apps//env — List vars
Use ?environment=production to filter. Secrets are masked as ab***cd.
{
"data": [
{ "id": "uuid", "key": "DATABASE_URL", "value": "po***db", "environment": "production", "is_secret": true }
]
}DELETE /api/v1/apps//env/
Use ?environment=production to delete a scoped var. Without the query param, deletes the unscoped (all-environments) version of the key.
Source config 🔒
Source config connects an app to a Git repository so POST .../deploy/trigger can build and deploy automatically. Only github is supported for triggered deploys today.
POST /api/v1/apps//source-config — Create / replace
Body
- source_type (string):
"github","gitlab", or"manual" - config (object): For GitHub —
{ "owner": "myorg", "repo": "my-app", "branch": "main" } - webhook_secret (string, optional): Used to verify incoming GitHub webhook payloads
curl -X POST http://localhost:47080/api/v1/apps/$APP_ID/source-config \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"source_type": "github",
"config": {"owner":"myorg","repo":"my-app","branch":"main"},
"webhook_secret": "whsec_abc..."
}'// 201 Created
{
"id": "uuid", "app_id": "uuid", "source_type": "github",
"config": { "owner": "myorg", "repo": "my-app", "branch": "main" },
"has_webhook_secret": true, "created_at": "...", "updated_at": "..."
}GET /api/v1/apps//source-config
Returns current config. Raw webhook secret is never returned; has_webhook_secret indicates whether one is set.
PUT /api/v1/apps//source-config — Update
Send only the fields to change — config and/or webhook_secret.
DELETE /api/v1/apps//source-config
204 No Content.
Custom domains
POST /api/v1/apps//custom-domains — Add
Body
- domain (string): e.g.
api.mycompany.com - path_prefix (string): e.g.
"/"
curl -X POST http://localhost:47080/api/v1/apps/$APP_ID/custom-domains \
-H 'Content-Type: application/json' \
-d '{"domain":"api.mycompany.com","path_prefix":"/"}'Point your DNS (A or CNAME) to the platform proxy. The proxy routes by Host header.
GET /api/v1/apps//custom-domains
List custom domain routes for the app.
DELETE /api/v1/apps//custom-domains/
204 No Content.
See also
- Deployments — create and manage deployments for an app
- Builds & artifacts — build from source or upload binaries