Management API
RESTREST API for deploying apps, provisioning databases, and managing infrastructure on the Sylphx Platform.
11 Resource Groups
Full platform coverage
50+ Endpoints
Everything you need
OpenAI-Compatible
Drop-in AI proxy
Bearer Auth
slx_cli_* tokens
Authentication
All endpoints require a Bearer token. Generate tokens at Dashboard → Settings → API Keys. Tokens are scoped to an organisation.
Authorization: Bearer slx_cli_xxxxxxxxxxxxxxxxFor the AI endpoints, set this token as your api_key and base_url = https://sylphx.com/api/v1 in any OpenAI client library.
Quick Navigation
Projects
Deploy and manage applications. Each project maps to a K8s Deployment.
/api/v1/projectsList all projects in the organisation.
Response
[
{
"id": "uuid",
"slug": "my-app",
"name": "My App",
"description": "...",
"isActive": true,
"environments": [...]
}
]/api/v1/projectsCreate a new project. Use Option A (Git-based) or Option B (pre-built Docker image).
Request Body
| Field | Type | Description |
|---|---|---|
| name* | string | Display name |
| slug* | string | URL-safe identifier |
| gitRepository | string | GitHub repo (owner/repo). Option A. |
| gitBranch | string | Branch to build (e.g. main). Option A. |
| buildPack | "dockerfile" | "nixpacks" | Build strategy. Option A. |
| dockerImage | string | Pre-built image reference. Option B. |
| port | number | Container port to expose. |
| domain | string | Hostname (e.g. myapp.sylphx.app). |
* required
Response
// 201 Created
{
"id": "uuid",
"slug": "my-app",
"name": "My App",
"isActive": true
}/api/v1/projects/:idGet a project by ID.
/api/v1/projects/:idUpdate project settings (name, description, domain, port, etc.).
Request Body
| Field | Type | Description |
|---|---|---|
| name | string | New display name. |
| description | string | Project description. |
| domain | string | Custom hostname. |
| port | number | Container port. |
* required
/api/v1/projects/:idDelete a project and all its resources (services, env vars, storage bindings).
Response
// 200 OK/api/v1/projects/:id/statusGet live Kubernetes status for a project.
Response
{
"status": "running",
"environment": "production",
"replicas": { "ready": 2, "desired": 2 }
}/api/v1/projects/:id/logsStream or fetch container 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"}/api/v1/projects/:id/deployTrigger a rolling deployment. Rebuilds the image from Git (if gitRepository is set) or re-deploys with updated env vars. Uses Kaniko in-cluster for Docker builds.
Request Body
| Field | Type | Description |
|---|---|---|
| envType | "production" | "staging" | "development" | Target environment. Default: production. |
* required
Response
{
"deploymentId": "uuid",
"status": "triggered",
"environment": "production"
}/api/v1/projects/:id/rollbackRoll back to a specific previous deployment. Traffic switches atomically — zero downtime.
Request Body
| Field | Type | Description |
|---|---|---|
| deploymentId* | string | ID of the deployment to restore. Get IDs from GET /deployments. |
* required
Response
{
"deploymentId": "uuid",
"status": "rolling-back",
"targetDeploymentId": "uuid"
}/api/v1/projects/:id/deploymentsList 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 stored encrypted in the Platform database. Injected into the container as env vars on every deploy. Values are never exposed in plaintext in list responses.
/api/v1/projects/:id/env-varsList 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 }
]/api/v1/projects/:id/env-varsSet (upsert) one or more env vars. This does NOT restart the container — call POST /deploy after to apply.
Request Body
| Field | Type | Description |
|---|---|---|
| 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, replicas, and domain.
/api/v1/projects/:id/environmentsList all environments for a project.
Response
[
{ "id": "uuid", "name": "production", "domain": "myapp.sylphx.app", "replicas": 2 },
{ "id": "uuid", "name": "staging", "domain": "staging-myapp.sylphx.app", "replicas": 1 }
]/api/v1/projects/:id/environmentsCreate a new environment for a project.
Request Body
| Field | Type | Description |
|---|---|---|
| name* | string | Environment name (e.g. "staging"). |
| domain | string | Custom hostname for this environment. |
| replicas | number | Number of replicas. Default: 1. |
* required
/api/v1/projects/:id/environments/:envIdGet a specific environment by ID.
/api/v1/projects/:id/environments/:envIdUpdate environment settings (domain, replicas, etc.).
Request Body
| Field | Type | Description |
|---|---|---|
| domain | string | New hostname. |
| replicas | number | New replica count. |
* required
/api/v1/projects/:id/environments/:envId/provisionProvision infra for a new environment (creates K8s namespace, secrets, HTTPRoute).
Services
A project can have multiple named services (e.g. web, worker, scheduler). Each service is an independent K8s Deployment with its own image, resources, and env.
/api/v1/projects/:id/servicesList all services for a project.
Response
[
{ "id": "uuid", "name": "web", "port": 3000, "replicas": 2, "status": "running" },
{ "id": "uuid", "name": "worker", "port": null, "replicas": 1, "status": "running" }
]/api/v1/projects/:id/servicesAdd a new named service to a project.
Request Body
| Field | Type | Description |
|---|---|---|
| name* | string | Service name (e.g. "worker"). |
| port | number | HTTP port to expose. Omit for background workers. |
| dockerfilePath | string | Path to Dockerfile. Default: Dockerfile. |
| replicas | number | Replica count. Default: 1. |
* required
/api/v1/projects/:id/services/:nameGet a specific service by name.
/api/v1/projects/:id/services/:nameUpdate service configuration (replicas, port, resources).
/api/v1/projects/:id/services/:name/environments/:envIdOverride service settings for a specific environment.
/api/v1/services/:serviceId/latest-imageGet the latest built image tag for a service (SHA-tagged from Harbor).
Response
{ "image": "registry.sylphx.com/sylphx/my-app:abc123def456" }/api/v1/services/:serviceId/tcp-proxyGet the TCP proxy config for a service (used to expose non-HTTP services).
Response
{
"enabled": true,
"externalPort": 5432,
"targetPort": 5432,
"allowlist": ["203.0.113.0/24"]
}/api/v1/services/:serviceId/tcp-proxyEnable TCP proxy for a service (e.g. expose a database port externally).
Request Body
| Field | Type | Description |
|---|---|---|
| externalPort* | number | NodePort to expose externally. |
| targetPort* | number | Container port to forward to. |
* required
/api/v1/services/:serviceId/tcp-proxyDisable the TCP proxy for a service. Add ?permanent=true to remove the NodePort allocation.
/api/v1/services/:serviceId/tcp-proxy/allowlistList IP allowlist rules for the TCP proxy.
/api/v1/services/:serviceId/tcp-proxy/allowlistAdd an IP CIDR to the allowlist.
Request Body
| Field | Type | Description |
|---|---|---|
| cidr* | string | CIDR block (e.g. "203.0.113.0/24"). |
| description | string | Human-readable label. |
* required
/api/v1/services/:serviceId/tcp-proxy/allowlist/:ruleIdRemove an allowlist rule.
Resources (Unified API)
Unified Management API for ALL resource kinds: databases (PostgreSQL/MySQL), KV stores (Redis), blob storage, search (Typesense), and volumes. One API, one auth model — works with both slx_cli_* tokens and browser cookies.
/api/v1/resourcesList all resources. Filter by kind using ?kind=database|kv|blob|search|volume.
Response
{
"object": "list",
"data": [
{ "id": "uuid", "kind": "database", "name": "Production DB", "reconcileStatus": "synced", ... },
{ "id": "uuid", "kind": "kv", "name": "My Redis", "reconcileStatus": "synced", ... }
]
}/api/v1/resourcesProvision any resource kind. Returns 202 immediately — provisioning is async. Poll GET /resources/:id for status.
Request Body
| Field | Type | Description |
|---|---|---|
| name* | string | Display name. |
| kind* | "database" | "kv" | "blob" | "search" | "volume" | Resource capability category. |
| provider | string | Underlying tech: database→postgresql|mysql, kv→redis|valkey, blob→b2|s3|r2, search→typesense, volume→ceph-rbd|ceph-fs. Platform picks a sensible default. |
| config | object | Provider-specific config (storageGb, maxMemoryMb, accessMode, etc.). |
| environmentId | string (uuid) | Optional: auto-bind to this environment after provisioning. |
* required
Response
// 202 Accepted — provisioning started
{
"id": "uuid",
"kind": "database",
"name": "Production DB",
"provider": "postgresql",
"reconcileStatus": "pending",
"status": "pending",
"message": "Database provisioning started. Poll GET /resources/:id for status.",
"createdAt": "2026-03-09T11:00:00Z"
}/api/v1/resources/:idGet a resource including live status, connection string (database/kv), and provider-specific config.
Response
// Database example
{
"id": "uuid",
"kind": "database",
"provider": "postgresql",
"name": "Production DB",
"status": "ready",
"tier": "standard",
"connectionString": "postgresql://app:secret@…:5432/app",
"maskedConnectionString": "postgresql://app:***@…:5432/app",
"publicConnectionString": "postgresql://app:[email protected]:5432/app",
"publicHost": "abc123.sylphx.net",
"backupRetentionDays": 14,
"createdAt": "2026-03-09T11:00:00Z"
}/api/v1/resources/:idUpdate resource name or config fields.
/api/v1/resources/:id⚠️ Deprovision and permanently delete the resource. Irreversible. Returns 204 No Content.
/api/v1/resources/:id/metricsGet Prometheus metrics for a resource. Adapts by kind (CNPG metrics for databases, Redis metrics for kv).
Response
// Database (CNPG)
{
"available": true,
"kind": "database",
"databaseSize": 1234567,
"cacheHitRatio": 0.97,
"activeConnections": 12,
"queryThroughput": [{ "t": 1709985600, "v": 42.3 }]
}
// KV (Redis)
{
"available": true,
"kind": "kv",
"memoryUsedBytes": 12345678,
"memoryUsedPercent": 48.2,
"hitRatio": 0.94,
"connectedClients": 5,
"commandsPerSec": [{ "t": 1709985600, "v": 120 }]
}/api/v1/resources/:id/backupsList CNPG backup snapshots. kind=database only (CNPG clusters). Returns 400 for other kinds.
Response
{
"available": true,
"backups": [
{ "name": "pg-abc123-backup-20260309", "status": "completed", "completedAt": "2026-03-09T02:00:00Z", "method": "plugin" }
]
}/api/v1/resources/:id/restorePITR restore to a point in time. Creates a NEW resource — does not overwrite the source.
Request Body
| Field | Type | Description |
|---|---|---|
| targetTime* | string (ISO 8601) | Point-in-time to restore to (max 7 days ago). |
* required
Response
// 202 Accepted
{
"restoreId": "uuid",
"restoredClusterName": "pg-abc123-r-1abc2d",
"targetTime": "2026-03-09T10:00:00Z",
"message": "Restore in progress, ready in ~5 min. Poll GET /resources/:restoreId for status."
}/api/v1/resources/:id/branchClone a database for staging/preview. fast=true uses a Ceph VolumeSnapshot (copy-on-write, ~60s). fast=false = fresh empty cluster.
Request Body
| Field | Type | Description |
|---|---|---|
| name | string | Branch resource name. |
| env | string | Target environment. Default: staging. |
| fast | boolean | true = snapshot clone (data copy), false = empty cluster. |
| storageGb | number | Branch storage size. Default: 10. |
* required
Response
// 201 Created — new database resource/api/v1/resources/:id/bindingsList 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"
}
]
}/api/v1/resources/:id/bindingsBind a resource to a project environment. Automatically syncs connection env vars (DATABASE_URL, REDIS_URL, etc.) to the deployment.
Request Body
| Field | Type | Description |
|---|---|---|
| projectEnvironmentId* | string (uuid) | Target project environment ID. |
| role | "primary" | "replica" | "analytics" | "backup" | Binding role. Default: primary. |
* required
/api/v1/resources/:id/bindings/:bindingIdRemove a resource binding. Cleans up injected env vars from the deployment.
Storage (Blob)
S3-compatible blob storage backed by Backblaze B2, served via CDN at storage.sylphx.com.
/api/v1/projects/:id/storageList storage resources attached to a project.
/api/v1/projects/:id/storageProvision blob storage for a project and get S3-compatible credentials.
Request Body
| Field | Type | Description |
|---|---|---|
| envType* | "production" | "staging" | "preview" | Environment. |
| name | string | Friendly name. Default: "primary". |
* required
Response
// 201 Created
{
"id": "uuid",
"publicUrl": "https://storage.sylphx.com/org/my-app/",
"envVars": {
"BLOB_ENDPOINT": "https://s3.eu-central-003.backblazeb2.com",
"BLOB_BUCKET": "sylphx-storage-prod",
"BLOB_PREFIX": "org/my-app/",
"BLOB_KEY_ID": "...",
"BLOB_APPLICATION_KEY": "...",
"BLOB_PUBLIC_URL": "https://storage.sylphx.com/org/my-app/"
}
}/api/v1/projects/:id/storage/:storageId⚠️ Delete a storage resource and revoke credentials. Does not delete existing blobs.
Volumes (Persistent Storage)
Persistent Ceph RBD volumes (rook-ceph-block, RWO) attached to a service for stateful data. Use this for uploaded files, caches, or any data that must survive pod restarts.
/api/v1/projects/:id/volumesList persistent volumes attached to a project.
Response
[
{ "id": "uuid", "name": "uploads", "mountPath": "/app/uploads", "sizeGb": 20, "status": "bound" }
]/api/v1/projects/:id/volumesCreate and attach a persistent volume.
Request Body
| Field | Type | Description |
|---|---|---|
| name* | string | Volume name (e.g. "uploads"). |
| mountPath* | string | Path inside the container to mount the volume. |
| sizeGb* | number | Volume size in GB. |
* required
/api/v1/projects/:id/volumes/:volIdGet a specific volume.
/api/v1/projects/:id/volumes/:volId⚠️ Delete a volume and its PVC. 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.
/api/v1/projects/:id/configList all config keys for a project.
Response
[
{ "key": "FEATURE_X", "value": "true" },
{ "key": "MAX_RETRIES", "value": "3" }
]/api/v1/projects/:id/configSet (upsert) multiple config keys at once.
Request Body
| Field | Type | Description |
|---|---|---|
| entries* | Array<{ key: string; value: string }> | Config entries to set. |
* required
/api/v1/projects/:id/config/:keyGet a specific config key.
Response
{ "key": "FEATURE_X", "value": "true" }/api/v1/projects/:id/config/:keySet (upsert) a single config key.
Request Body
| Field | Type | Description |
|---|---|---|
| value* | string | Value to store. |
* required
/api/v1/projects/:id/config/:keyDelete a config key.
AI / LLM
OpenAI-compatible API that proxies to configured LLM providers. Use your Sylphx token as the api_key.
/api/v1/chat/completionsOpenAI-compatible chat completions. Set base_url = https://sylphx.com/api/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 }
}/api/v1/embeddingsGenerate text embeddings. OpenAI-compatible format.
/api/v1/modelsList 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.
/api/v1/health/statusOverall platform health check.
Response
{
"status": "healthy",
"services": {
"database": "ok",
"kubernetes": "ok",
"storage": "ok"
},
"timestamp": "2026-03-09T11:00:00Z"
}/api/v1/health/runnersGitHub 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": "..." }| Status | Meaning |
|---|---|
| 400 | Bad request / invalid body |
| 401 | Missing or invalid Bearer token |
| 403 | Token valid but no access to this resource |
| 404 | Resource not found |
| 409 | Conflict (e.g. slug already taken) |
| 500 | Internal server error |
Quick Reference (curl)
BASE="https://sylphx.com/api/v1"
TOKEN="slx_cli_YOUR_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","provider":"postgresql","config":{"env":"production","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 Redis KV store
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
-d '{"name":"My Redis","kind":"kv","provider":"redis","config":{"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