synsema

API reference

The platform, from a terminal or an agent.

Everything the dashboard does, the CLI, a runner or your own agent can do over HTTPS. Get a token from Settings or with the login call, then send it as Authorization: Bearer <token>. The machine-readable version is openapi.json; agents also read llms.txt.

POST /api/v1/auth/login

Exchange email and password for an API token

Body: {"email": "string", "password": "string"}

Returns: {token, user}

curl -X POST https://control-1.synsema.com/api/v1/auth/login -H 'Content-Type: application/json' -d '{"email": "you@example.com", "password": "…"}'

GET /api/v1/me bearer

The account behind the token

Returns: {id, email, name, plan, admin, via}

curl https://control-1.synsema.com/api/v1/me -H "Authorization: Bearer $SYN_TOKEN"

GET /api/v1/recipes

The recipe catalog, mirrored from github.com/synsema/recipes

Returns: {items: [{slug, name, version, kind, entry, repo, ref, secrets, tagline, tagline_es, tagline_pt}]}

curl https://control-1.synsema.com/api/v1/recipes

GET /api/v1/projects bearer

Your projects

Returns: {items: [project]}

curl https://control-1.synsema.com/api/v1/projects -H "Authorization: Bearer $SYN_TOKEN"

POST /api/v1/projects bearer

Create a project: from files (the package `syn deploy` sends), a recipe, a public GitHub repository, or one pasted entry file

Body: {"name": "string", "files": "[{path, content, encoding: utf8 | base64}] (optional)", "recipe": "slug (optional)", "repo": "https://github.com/owner/repo (optional)", "ref": "branch or tag (optional, with repo)", "source": "string, the entry file (optional)", "entry": "string (optional)", "kind": "web | worker (optional)"}

Returns: {project, ceiling, package, missing_secrets}

curl -X POST https://control-1.synsema.com/api/v1/projects -H "Authorization: Bearer $SYN_TOKEN" -H 'Content-Type: application/json' -d '{"name": "lampson", "recipe": "lampson"}'

GET /api/v1/projects/{id} bearer

One project, its effective ceiling, package, missing secrets and deploys

Returns: {project, ceiling, package, missing_secrets, deploys}

curl https://control-1.synsema.com/api/v1/projects/1 -H "Authorization: Bearer $SYN_TOKEN"

GET /api/v1/projects/{id}/package bearer

The current files of the project

Returns: {entry, kind, package, files: [{path, content, encoding}]}

curl https://control-1.synsema.com/api/v1/projects/1/package -H "Authorization: Bearer $SYN_TOKEN"

POST /api/v1/projects/{id}/deploys bearer

Queue a deploy of the current package, or send a new one first

Body: {"files": "[{path, content, encoding}] (optional, a new package)", "entry": "string (optional, with files)", "source": "string (optional, replaces the entry file)"}

Returns: {deploy, ceiling, missing_secrets, url, logs}

curl -X POST https://control-1.synsema.com/api/v1/projects/1/deploys -H "Authorization: Bearer $SYN_TOKEN"

GET /api/v1/projects/{id}/deploys/{did} bearer

One deploy and the ceiling it was given

Returns: deploy

curl https://control-1.synsema.com/api/v1/projects/1/deploys/1 -H "Authorization: Bearer $SYN_TOKEN"

GET /api/v1/projects/{id}/logs bearer

Live logs as server-sent events (event: log)

Returns: text/event-stream

curl -N https://control-1.synsema.com/api/v1/projects/1/logs -H "Authorization: Bearer $SYN_TOKEN"

GET /api/v1/projects/{id}/logs/tail bearer

Log lines after an id, as JSON (?after=<id>); what `syn logs` polls

Returns: {items: [{id, at, line}], last}

curl "https://control-1.synsema.com/api/v1/projects/1/logs/tail?after=0" -H "Authorization: Bearer $SYN_TOKEN"

GET /api/v1/projects/{id}/audit bearer

Every capability check, declared versus done (?only=granted|denied)

Returns: {items: [{ts, capability, scope, granted, origin, why}]}

curl "https://control-1.synsema.com/api/v1/projects/1/audit?only=denied" -H "Authorization: Bearer $SYN_TOKEN"

GET /api/v1/projects/{id}/secrets bearer

The secrets set (names and fingerprints, never values) and the ones the manifest still needs

Returns: {items: [{name, fingerprint, created_at}], missing: [name]}

curl https://control-1.synsema.com/api/v1/projects/1/secrets -H "Authorization: Bearer $SYN_TOKEN"

PUT /api/v1/projects/{id}/secrets/{name} bearer

Set a secret (UPPER_SNAKE_CASE); the value is never returned

Body: {"value": "string"}

Returns: {ok, name}

curl -X PUT https://control-1.synsema.com/api/v1/projects/1/secrets/LLM_API_KEY -H "Authorization: Bearer $SYN_TOKEN" -H 'Content-Type: application/json' -d '{"value": "sk-…"}'