Skip to main content

Management API

REST

REST API for deploying apps, provisioning databases, and managing infrastructure on the Sylphx Platform.

Base URL: https://sylphx.com/api/v1

11 Resource Groups

Full platform coverage

50+ Endpoints

Everything you need

OpenAI-Compatible

Drop-in AI proxy

Bearer Auth

slx_* PAT tokens

Authentication

All endpoints require a Bearer token. Generate tokens at Dashboard → Settings → API Keys. Tokens are scoped to an organisation.

Authorization: Bearer slx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

For the AI endpoints, set this token as your api_key and base_url = https://api.sylphx.ai/v1 in any OpenAI client library.

Method colours:GETPOSTDELETEPUTPATCH uses same colour as PUT

Projects

Deploy and manage applications across environments.

GET/api/v1/projects

List all projects in the organisation.

Response

[
  {
    "id": "uuid",
    "slug": "my-app",
    "name": "My App",
    "description": "...",
    "isActive": true,
    "environments": [...]
  }
]
POST/api/v1/projects

Create a new project. Use Option A (Git-based) or Option B (pre-built Docker image).

Request Body

FieldTypeDescription
name*stringDisplay name
slug*stringURL-safe identifier
gitRepositorystringGitHub repo (owner/repo). Option A.
gitBranchstringBranch to build (e.g. main). Option A.
buildPack"dockerfile" | "nixpacks"Build strategy. Option A.
dockerImagestringPre-built image reference. Option B.
portnumberService port to expose.
domainstringHostname (e.g. myapp.sylphx.app).

* required

Response

// 201 Created
{
  "id": "uuid",
  "slug": "my-app",
  "name": "My App",
  "isActive": true
}
GET/api/v1/projects/:id

Get a project by ID.

PATCH/api/v1/projects/:id

Update project settings (name, description, domain, port, etc.).

Request Body

FieldTypeDescription
namestringNew display name.
descriptionstringProject description.
domainstringCustom hostname.
portnumberService port.

* required

DELETE/api/v1/projects/:id

Delete a project and all its resources (services, env vars, storage bindings).

Response

// 200 OK
GET/api/v1/projects/:id/status

Get live deployment status for a project.

Response

{
  "projectId": "proj_xxx",
  "projectSlug": "myapp",
  "projectName": "My App",
  "isActive": true,
  "status": "running",
  "environments": [
    {
      "envId": "env_xxx",
      "envType": "production",
      "status": "running",
      "url": "https://myapp.sylphx.app"
    }
  ]
}
GET/api/v1/projects/:id/logs

Stream or fetch service logs. Query params: envType (default production), tail (default 200, max 1000), stream=true for SSE streaming, deploymentId to scope to a specific build.

Response

// Newline-delimited log lines (stream=false)
2026-03-09T11:00:00Z [web] Server listening on :3000
2026-03-09T11:00:01Z [web] GET /healthz 200

// Server-Sent Events (stream=true)
data: {"ts":"2026-03-09T11:00:00Z","level":"info","msg":"Server listening on :3000"}
POST/api/v1/projects/:id/deploy

Trigger a rolling deployment. Rebuilds from Git (if gitRepository is set) or re-deploys with updated env vars.

💡 Always call this after updating env vars to apply changes.

Request Body

FieldTypeDescription
envType"production" | "staging" | "development"Target environment. Default: production.

* required

Response

{
  "deploymentId": "uuid",
  "status": "triggered",
  "environment": "production"
}
POST/api/v1/projects/:id/rollback

Roll back to a specific previous deployment. Traffic switches atomically — zero downtime.

💡 Rolling back does not revert env var changes — update env vars separately if needed.

Request Body

FieldTypeDescription
deploymentId*stringID of the deployment to restore. Get IDs from GET /deployments.

* required

Response

{
  "deploymentId": "uuid",
  "status": "rolling-back",
  "targetDeploymentId": "uuid"
}
GET/api/v1/projects/:id/deployments

List deployment history. Query params: envType, limit (default 20, max 100).

Response

[
  {
    "id": "uuid",
    "status": "success",
    "gitCommit": "abc1234",
    "gitBranch": "main",
    "triggeredBy": "push",
    "startedAt": "2026-03-09T11:00:00Z",
    "finishedAt": "2026-03-09T11:02:30Z"
  }
]

Environment Variables

Secrets are stored encrypted and injected as env vars on every deploy. Values are never exposed in plaintext in list responses.

GET/api/v1/projects/:id/env-vars

List env vars for a project. Query params: envType (default production), envId. Secret values are masked as "***".

Response

[
  { "key": "DATABASE_URL", "value": "***", "secret": true },
  { "key": "PORT", "value": "3000", "secret": false }
]
POST/api/v1/projects/:id/env-vars

Set (upsert) one or more env vars. This does NOT restart the service — call POST /deploy after to apply.

💡 After setting vars, call POST /projects/:id/deploy to apply them to the running service.

Request Body

FieldTypeDescription
envType*"production" | "staging" | "development"Target environment.
vars*Array<{ key: string; value: string; secret?: boolean }>Variables to set. secret=true masks values in the dashboard and logs.

* required

Environments

Manage deployment environments per project (production, staging, preview). Each environment has its own env vars, branch policy, protection, and domains.

GET/api/v1/projects/:id/environments

List all environments for a project.

Response

[
  { "id": "env_xxx", "name": "production", "envType": "production", "isActive": true },
  { "id": "env_yyy", "name": "staging", "envType": "staging", "isActive": true }
]
POST/api/v1/projects/:id/environments

Create a new environment for a project.

Request Body

FieldTypeDescription
name*stringEnvironment name (e.g. "staging").
envType"production" | "staging" | "preview"Environment type.
autoDeploybooleanWhether Git pushes deploy automatically.

* required

GET/api/v1/projects/:id/environments/:envId

Get a specific environment by ID.

PATCH/api/v1/projects/:id/environments/:envId

Update environment settings.

Request Body

FieldTypeDescription
autoDeploybooleanWhether Git pushes deploy automatically.
protection"open" | "login-required"Access policy for public services.

* required

POST/api/v1/projects/:id/environments/:envId/provision

Start or refresh managed environment provisioning.

Services

A project can have multiple named services (e.g. web, worker, scheduler). Each service has its own image, resources, and env.

GET/api/v1/projects/:id/services

List all services for a project.

Response

[
  { "id": "svc_xxx", "name": "web",    "port": 3000, "status": "running" },
  { "id": "svc_yyy", "name": "worker", "port": null,  "status": "running" }
]
POST/api/v1/projects/:id/services

Add a new named service to a project.

Request Body

FieldTypeDescription
name*stringService name (e.g. "worker").
portnumberHTTP port to expose. Omit for background workers.
dockerfilePathstringPath to Dockerfile. Default: Dockerfile.
instanceTypestringService tier for compute sizing.

* required

GET/api/v1/projects/:id/services/:name

Get a specific service by name.

PATCH/api/v1/projects/:id/services/:name

Update service configuration (scale, port, and service tier).

PATCH/api/v1/projects/:id/services/:name/environments/:envId

Override service settings for a specific environment.

GET/api/v1/services/:serviceId/tcp-proxy

Get the TCP proxy config for a service (used to expose non-HTTP services).

Response

{
  "enabled": true,
  "endpoint": {
    "host": "proxy.sylphx.net",
    "port": 18432,
    "protocol": "tcp",
    "allowlist": [{ "id": "prule_01j8x9...", "cidr": "203.0.113.0/24", "label": "office" }]
  }
}
POST/api/v1/services/:serviceId/tcp-proxy

Enable TCP proxy for a service. The platform routes traffic to the latest healthy deploy.

Request Body

FieldTypeDescription
portnumberOptional service port. Defaults to the configured service port.

* required

DELETE/api/v1/services/:serviceId/tcp-proxy

Disable the TCP proxy for a service. Add ?permanent=true to remove the endpoint allocation.

GET/api/v1/services/:serviceId/tcp-proxy/allowlist

List IP allowlist rules for the TCP proxy.

Response

{
  "data": [{ "id": "prule_01j8x9...", "cidr": "203.0.113.0/24", "label": "office" }]
}
POST/api/v1/services/:serviceId/tcp-proxy/allowlist

Add an IP CIDR to the allowlist.

Request Body

FieldTypeDescription
cidr*stringCIDR block (e.g. "203.0.113.0/24").
descriptionstringHuman-readable label.

* required

DELETE/api/v1/services/:serviceId/tcp-proxy/allowlist/:ruleId

Remove an allowlist rule.

Resources (Unified API)

Unified Management API for all resource kinds: databases, managed cache, blob storage, search, and volumes. One API, one auth model — works with both slx_* PAT tokens and browser cookies.

GET/api/v1/resources

List all resources. Filter by kind using ?kind=database|kv|blob|search|volume.

Response

{
  "object": "list",
  "data": [
    { "id": "uuid", "kind": "database", "name": "Production DB", "status": "ready", ... },
    { "id": "uuid", "kind": "kv",       "name": "App Cache",     "status": "ready", ... }
  ]
}
POST/api/v1/resources

Provision any resource kind. Returns 202 immediately — provisioning is async. Poll GET /resources/:id for status.

💡 Poll GET /resources/:id until status === "ready" (~60–90s). Bind the resource to an environment to receive managed env vars such as DATABASE_URL or CACHE_URL.

Request Body

FieldTypeDescription
name*stringDisplay name.
kind*"database" | "kv" | "blob" | "search" | "volume"Resource capability category.
tierstringOptional product tier. The platform chooses the runtime shape.
storageGbnumberOptional storage size for durable resources.

* required

Response

// 202 Accepted — provisioning started
{
  "id": "uuid",
  "kind": "database",
  "name": "Production DB",
  "status": "provisioning",
  "message": "Database provisioning started. Poll GET /resources/:id for status.",
  "createdAt": "2026-03-09T11:00:00Z"
}
GET/api/v1/resources/:id

Get a resource including live status, product endpoint hints, and managed env-var names.

Response

// Database example
{
  "id": "uuid",
  "kind": "database",
  "name": "Production DB",
  "status": "ready",
  "tier": "standard",
  "endpoint": { "host": "abc123.sylphx.net", "port": 5432, "protocol": "postgresql" },
  "connection": { "env": ["DATABASE_URL", "DATABASE_URL_UNPOOLED"], "maskedUrl": "postgresql://app:***@abc123.sylphx.net:5432/app" },
  "backupRetentionDays": 14,
  "createdAt": "2026-03-09T11:00:00Z"
}
PATCH/api/v1/resources/:id

Update resource name or product-level settings.

DELETE/api/v1/resources/:id

⚠️ Deprovision and permanently delete the resource. Irreversible. Returns 204 No Content.

GET/api/v1/resources/:id/metrics

Get managed metrics for a resource. Adapts by kind for databases, kv, search, and storage.

Response

// Database
{
  "available": true,
  "kind": "database",
  "databaseSize": 1234567,
  "cacheHitRatio": 0.97,
  "activeConnections": 12,
  "queryThroughput": [{ "t": 1709985600, "v": 42.3 }]
}

// Managed cache
{
  "available": true,
  "kind": "kv",
  "memoryUsedBytes": 12345678,
  "memoryUsedPercent": 48.2,
  "hitRatio": 0.94,
  "connectedClients": 5,
  "commandsPerSec": [{ "t": 1709985600, "v": 120 }]
}
GET/api/v1/resources/:id/backups

List managed database backup snapshots. kind=database only. Returns 400 for other kinds.

Response

{
  "available": true,
  "backups": [
    { "name": "pg-abc123-backup-20260309", "status": "completed", "completedAt": "2026-03-09T02:00:00Z", "method": "plugin" }
  ]
}
POST/api/v1/resources/:id/restore

PITR restore to a point in time. Creates a NEW resource — does not overwrite the source.

💡 Restore creates a new database resource. Poll GET /resources/:restoreId until status === "ready".

Request Body

FieldTypeDescription
targetTime*string (ISO 8601)Point-in-time to restore to (max 7 days ago).

* required

Response

// 202 Accepted
{
  "restoreId": "uuid",
  "resourceId": "res_abc123",
  "targetTime": "2026-03-09T10:00:00Z",
  "message": "Restore in progress, ready in ~5 min. Poll GET /resources/:resourceId for status."
}
POST/api/v1/resources/:id/branch

Clone a database for staging/preview. fast=true uses the platform-optimized clone path (~60s). fast=false creates an empty branch.

Request Body

FieldTypeDescription
namestringBranch resource name.
envstringTarget environment. Default: staging.
fastbooleantrue = snapshot clone (data copy), false = empty database.
storageGbnumberBranch storage size. Default: 10.

* required

Response

// 201 Created — new database resource
GET/api/v1/resources/:id/bindings

List all project environment bindings for this resource.

Response

{
  "bindings": [
    {
      "id": "uuid",
      "projectEnvironmentId": "uuid",
      "resourceType": "database",
      "role": "primary",
      "envName": "production",
      "projectName": "My App",
      "projectSlug": "my-app",
      "createdAt": "2026-03-09T11:00:00Z"
    }
  ]
}
POST/api/v1/resources/:id/bindings

Bind a resource to a project environment. Automatically syncs connection env vars (DATABASE_URL, CACHE_URL, etc.) to the deployment.

Request Body

FieldTypeDescription
projectEnvironmentId*string (uuid)Target project environment ID.
role"primary" | "read" | "analytics" | "backup"Binding role. Default: primary.

* required

DELETE/api/v1/resources/:id/bindings/:bindingId

Remove a resource binding. Cleans up injected env vars from the deployment.

Storage (Blob)

Managed object storage served via CDN at storage.sylphx.com.

GET/api/v1/projects/:id/storage

List storage resources attached to a project.

POST/api/v1/projects/:id/storage

Provision and bind managed blob storage for a project.

💡 Storage backend credentials stay managed by Sylphx and are not exposed to deployments.

Request Body

FieldTypeDescription
envType*"production" | "staging" | "preview"Environment.
namestringFriendly name. Default: "primary".

* required

Response

// 201 Created
{
  "id": "bnd_01...",
  "resourceId": "res_01...",
  "role": "primary",
  "envType": "production",
  "publicUrl": "https://storage.sylphx.com/org/my-app/",
  "envVars": {
    "BLOB_PUBLIC_URL":      "https://storage.sylphx.com/org/my-app/"
  },
  "envVarNames": ["BLOB_PUBLIC_URL"]
}
DELETE/api/v1/projects/:id/storage/:storageId

⚠️ Delete a storage resource and revoke credentials. Does not delete existing blobs.

Volumes (Durable Storage)

Durable volumes attached to services or tasks for uploaded files, caches, and app data.

GET/api/v1/projects/:id/volumes

List volumes attached to a project.

Response

[
  { "id": "uuid", "name": "uploads", "mountPath": "/app/uploads", "sizeGb": 20, "status": "bound" }
]
POST/api/v1/projects/:id/volumes

Create and attach a volume.

Request Body

FieldTypeDescription
name*stringVolume name (e.g. "uploads").
mountPath*stringPath inside the service filesystem to mount the volume.
sizeGb*numberVolume size in GB.

* required

GET/api/v1/projects/:id/volumes/:volId

Get a specific volume.

DELETE/api/v1/projects/:id/volumes/:volId

⚠️ Delete a volume. All data on the volume is permanently lost.

Config

Key-value config store scoped to a project. For non-secret runtime configuration (feature switches, thresholds). Not injected as env vars — read via SDK or API.

GET/api/v1/projects/:id/config

List all config keys for a project.

Response

[
  { "key": "FEATURE_X", "value": "true" },
  { "key": "MAX_RETRIES", "value": "3" }
]
POST/api/v1/projects/:id/config

Set (upsert) multiple config keys at once.

Request Body

FieldTypeDescription
entries*Array<{ key: string; value: string }>Config entries to set.

* required

GET/api/v1/projects/:id/config/:key

Get a specific config key.

Response

{ "key": "FEATURE_X", "value": "true" }
PUT/api/v1/projects/:id/config/:key

Set (upsert) a single config key.

Request Body

FieldTypeDescription
value*stringValue to store.

* required

DELETE/api/v1/projects/:id/config/:key

Delete a config key.

AI / LLM

OpenAI-compatible API that proxies to configured LLM providers. Use your Sylphx token as the api_key.

POST/api/v1/chat/completions

OpenAI-compatible chat completions. Set base_url = https://api.sylphx.ai/v1 in any OpenAI SDK.

Response

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "choices": [{ "message": { "role": "assistant", "content": "..." } }],
  "usage": { "prompt_tokens": 12, "completion_tokens": 34, "total_tokens": 46 }
}
POST/api/v1/embeddings

Generate text embeddings. OpenAI-compatible format.

GET/api/v1/models

List all available models (chat + embedding).

Response

{
  "object": "list",
  "data": [
    { "id": "gpt-4o", "object": "model" },
    { "id": "claude-3-5-sonnet", "object": "model" },
    { "id": "text-embedding-3-small", "object": "model" }
  ]
}

Health

Platform health and runner status. No auth required.

GET/api/v1/health/status

Overall platform health check.

Response

{
  "services": [
    {
      "name": "Platform API",
      "description": "Console, dashboard, and API endpoints",
      "status": "operational",
      "latencyMs": 42
    }
  ],
  "overall": "operational",
  "checkedAt": "2026-03-09T11:00:00Z",
  "release": {
    "version": "feaef05b33c8",
    "commitSha": "feaef05b33c83474006936e12d560b05d1ef474c",
    "imageDigest": "sha256:...",
    "deploymentId": "dep_..."
  }
}
GET/api/v1/health/runners

GitHub ARC runner pool status — idle, busy, and offline counts.

Response

{
  "runners": [
    { "name": "runner-abc", "status": "idle",  "labels": ["linux", "x64"] },
    { "name": "runner-def", "status": "busy",  "labels": ["linux", "x64"] }
  ],
  "summary": { "idle": 1, "busy": 1, "offline": 0 }
}

Error Responses

All errors return a JSON body with error and optional details fields.

{ "error": "Human-readable message", "details": "..." }
StatusMeaning
400Bad request / invalid body
401Missing or invalid Bearer token
403Token valid but no access to this resource
404Resource not found
409Conflict (e.g. slug already taken)
500Internal server error

Quick Reference (curl)

BASE="https://api.sylphx.com/v1"
TOKEN="slx_YOUR_PAT_TOKEN_HERE"
AUTH="Authorization: Bearer $TOKEN"

# ── Projects ──────────────────────────────────────────────
curl -H "$AUTH" $BASE/projects                                # list
curl -H "$AUTH" $BASE/projects/{ID}                           # get
curl -H "$AUTH" $BASE/projects/{ID}/status                    # live status
curl -H "$AUTH" "$BASE/projects/{ID}/logs?tail=200"           # logs

# Deploy (rebuild + rollout)
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"envType":"production"}' $BASE/projects/{ID}/deploy

# Rollback to a previous deployment
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"deploymentId":"DEPLOY_ID"}' $BASE/projects/{ID}/rollback

# ── Environment Variables ─────────────────────────────────
curl -H "$AUTH" "$BASE/projects/{ID}/env-vars?envType=production"
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"envType":"production","vars":[{"key":"MY_VAR","value":"hello","secret":true}]}' \
  $BASE/projects/{ID}/env-vars
# (then deploy to apply)

# ── Resources (Unified API) ───────────────────────────────
# Provision a PostgreSQL database
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"name":"My DB","kind":"database","tier":"standard","storageGb":10}' \
  $BASE/resources                                             # provision (202)
curl -H "$AUTH" $BASE/resources/{ID}                          # get + connection string
curl -H "$AUTH" $BASE/resources/{ID}/metrics                  # metrics
curl -H "$AUTH" $BASE/resources/{ID}/backups                  # list backups (database only)
curl -X DELETE -H "$AUTH" $BASE/resources/{ID}                # ⚠️ delete

# Provision a managed cache
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"name":"App Cache","kind":"kv","tier":"standard","storageGb":5}' \
  $BASE/resources                                             # provision (202)
curl -H "$AUTH" $BASE/resources/{ID}                          # get + connection string

# Filter resources by kind
curl -H "$AUTH" "$BASE/resources?kind=database"               # list all databases
curl -H "$AUTH" "$BASE/resources?kind=kv"                     # list all KV stores

# ── Storage ───────────────────────────────────────────────
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"envType":"production","name":"primary"}' \
  $BASE/projects/{ID}/storage                                 # provision
curl -H "$AUTH" $BASE/projects/{ID}/storage                   # list

# ── AI / LLM ──────────────────────────────────────────────
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}' \
  $BASE/chat/completions

# ── Health ────────────────────────────────────────────────
curl $BASE/health/status