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-…"}'