Skip to content
Console
Menu

Getting Started

Authentication

KV Store

Compute & deliveryREST

Management API

REST API for Project, Environment, Service, hostname, and Cloud credentials. Databases, auth, and models are independent products — not Cloud SKUs.

Base URL
https://api.sylphx.com/v1
Auth
Bearer svc_… service token
Console
/console
Base URL: https://api.sylphx.com/v1

Hosting contract

Project, Environment, Service

Hostnames

Preview through production

Cloud credentials

Cloud APIs only

Bearer Auth

svc_* service tokens

Authentication

All endpoints require a Bearer token. Three ways to authenticate:

  • OAuth login — sylphx login (device flow); the CLI manages tokens for you.
  • Service tokens (svc_*) — sylphx tokens create <name> --scopes ... --expires-in ..., scoped to an organisation. For CI and agents, set SYLPHX_TOKEN.
  • OIDC federation — exchange a CI provider's OIDC JWT (GitHub Actions, GitLab, ...) for a short-lived token via POST /oidc/exchange. Scaffold with sylphx ci init github.
Authorization: Bearer svc_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/projects

List all projects in the organisation.

Response

[
  {
    "id": "uuid",
    "slug": "my-app",
    "name": "My App",
    "description": "...",
    "isActive": true,
    "environments": [...]
  }
]
POST/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"auto" | "buildpack" | "dockerfile"Build strategy. Option A. Legacy nixpacks manifests are compatibility-only; new configs use Sylphx Buildpack or Dockerfile.
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/projects/:id

Get a project by ID.

PATCH/projects/:id

Update project settings (name, description, domains, build machine, etc.).

Request Body

FieldTypeDescription
namestringNew display name.
descriptionstringProject description.
domainsstring[]Custom hostnames.
buildMachineType"standard" | "large" | "xlarge" | "2xlarge"CI build machine tier.

* required

DELETE/projects/:id

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

Response

// 200 OK
GET/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/environments/:envId/logs

Stream or tail environment logs (build or runtime). Query params: type (build | runtime), stream=true for SSE streaming, deploymentId, since, level, limit, service. Get envId from GET /projects/:id/environments.

Response

// JSON list (stream omitted)
{
  "object": "list",
  "envId": "env_xxx",
  "data": [
    { "timestamp": "2026-03-09T11:00:00Z", "level": "info", "message": "Server listening on :3000" }
  ]
}

// Server-Sent Events (stream=true)
data: {"timestamp":"2026-03-09T11:00:00Z","level":"info","message":"Server listening on :3000"}
POST/projects/:id/deployments

Create an immutable Deployment from a trusted completedBuildId and serviceId. Use an Idempotency-Key header. Returns a durable Operation.

GET/projects/:id/deployments

List immutable build results and provenance. Filter by serviceId; paginate with pageToken and pageSize. Environment progress belongs to Releases.

GET/projects/:id/environments/:envId/delivery-policy

Read the effective policy ID, revision, version, automatic-build switch, promotion mode, and typed verification requirements.

PATCH/projects/:id/environments/:envId/delivery-policy

Patch the policy using expectedPolicyRevision, expectedPolicyVersion, patch, and an Idempotency-Key header. Omission preserves fields; requiredProofs: {items: []} explicitly clears requirements. Returns an Operation.

GET/projects/:id/environments/:envId/services/:serviceId/delivery-configuration

Inspect the current configuration authoringRevision and exact secret version references for a service before selecting it into a Release.

POST/projects/:id/environments/:envId/releases

Create an immutable complete service set with policyRevision, members, and optional previousReleaseId. Selected members bind serviceId, deploymentId, and expectedAuthoringRevision from the inspected configuration. Carried members bind the exact carriedFromReleaseId and carriedFromMemberId. The server seals the complete configuration and rejects concurrent authoring changes. Returns an Operation.

GET/projects/:id/environments/:envId/releases

List actual Environment Releases with distinct status and per-member observations. Paginate with pageToken and pageSize.

GET/projects/:id/environments/:envId/releases/:releaseId

Inspect exact Release intent, policy revision, selection generation, and observed member status. Its /receipts and /decisions subresources expose evidence and admission outcomes.

POST/projects/:id/environments/:envId/releases/:releaseId:promote

Request policy-preserving promotion with expectedPolicyRevision, expectedSelectionGeneration, and an Idempotency-Key header. Recovery creates a new complete Release from retained trusted Deployments and requests promotion; it never rebuilds source or bypasses policy.

Environment Variables

Secrets are stored encrypted and injected as env vars on every deploy. Values are write-only — decrypted values never leave the server.

GET/projects/:id/env-vars

List env var keys for a project/environment. Query params: envType (default production), envId, serviceId. Returns key-only rows — values are never returned.

Response

{
  "object": "list",
  "envId": "env_xxx",
  "envType": "production",
  "scope": "environment",
  "data": [
    { "key": "DATABASE_URL", "secret": true },
    { "key": "PORT", "secret": false }
  ]
}
POST/projects/:id/env-vars

Set (upsert) one or more env vars (env-level or per-service). Create a new Release referencing the resulting exact secret/configuration versions, then request promotion.

💡 After setting variables, create and promote a new Release with the exact secret versions.

Request Body

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

* required

DELETE/projects/:id/env-vars/:key

Delete an env var by key. Query params: envType, envId, serviceId.

Response

{ "deleted": true, "key": "MY_VAR", "scope": "environment", "serviceId": null }

Environments

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

GET/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/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.

* required

GET/projects/:id/environments/:envId

Get a specific environment by ID.

PATCH/projects/:id/environments/:envId

Update environment settings.

Request Body

FieldTypeDescription
protection"open" | "login-required"Access policy for public services.

* required

POST/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/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/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/projects/:id/services/:name

Get a specific service by name.

PATCH/projects/:id/services/:name

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

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

Override service settings for a specific environment.

GET/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/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/services/:serviceId/tcp-proxy

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

GET/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/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/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 svc_* service tokens and browser cookies.

GET/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/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/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/resources/:id

Update resource name or product-level settings.

DELETE/resources/:id

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

GET/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/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/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/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/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/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/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/projects/:id/storage

List storage resources attached to a project.

POST/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/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/projects/:id/volumes

List volumes attached to a project.

Response

[
  { "id": "uuid", "name": "uploads", "mountPath": "/app/uploads", "sizeGb": 20, "status": "bound" }
]
POST/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/projects/:id/volumes/:volId

Get a specific volume.

DELETE/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/projects/:id/config

List all config keys for a project.

Response

[
  { "key": "FEATURE_X", "value": "true" },
  { "key": "MAX_RETRIES", "value": "3" }
]
POST/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/projects/:id/config/:key

Get a specific config key.

Response

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

Set (upsert) a single config key.

Request Body

FieldTypeDescription
value*stringValue to store.

* required

DELETE/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/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/embeddings

Generate text embeddings. OpenAI-compatible format.

GET/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/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/health/runners

JIT 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="svc_<your-token>"   # sylphx tokens create ci --scopes project:deploy
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

# Register a completed build, then inspect the Operation before using its Deployment
curl -X POST -H "$AUTH" -H "Content-Type: application/json" -H "Idempotency-Key: BUILD_REQUEST_KEY" \
  -d '{"serviceId":"SERVICE_ID","completedBuildId":"BUILD_ID"}' $BASE/projects/{ID}/deployments

# Read exact policy before creating an Environment Release
curl -H "$AUTH" $BASE/projects/{ID}/environments/{ENV_ID}/delivery-policy
# Inspect each selected service configuration before choosing its Deployment
curl -H "$AUTH" $BASE/projects/{ID}/environments/{ENV_ID}/services/{SERVICE_ID}/delivery-configuration
# release.json contains policyRevision, complete members, and optional previousReleaseId
# Selected members carry expectedAuthoringRevision from the inspected configuration
curl -X POST -H "$AUTH" -H "Content-Type: application/json" -H "Idempotency-Key: RELEASE_REQUEST_KEY" \
  --data-binary @release.json $BASE/projects/{ID}/environments/{ENV_ID}/releases
# Promotion selects those same immutable artifacts and rechecks policy
curl -X POST -H "$AUTH" -H "Content-Type: application/json" -H "Idempotency-Key: PROMOTE_REQUEST_KEY" \
  -d '{"mode":"OPERATION_MODE_APPLY","expectedPolicyRevision":"POLICY_REVISION","expectedSelectionGeneration":"0"}' \
  $BASE/projects/{ID}/environments/{ENV_ID}/releases/{RELEASE_ID}:promote

# ── 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
# Create and promote a new Release with the resulting exact secret versions.

# ── 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