API
The 5050cloud REST API serves everything the console and the CLI do, with the same roles and audit log.
Basics
- Base URL:
https://<your console domain>/api/v1. Health endpoints/healthzand/readyzsit at the root. - Authentication:
Authorization: Bearer 5050_...with an API token from Account > Tokens or5050 login. Browser sessions use the5050_sessioncookie and must send the headerX-5050-CSRF: 1on every request that changes state. - Scopes: an
accounttoken acts as its user. Anenvironmenttoken can deploy, read logs and set variables in one environment. - Roles: Public needs no login. Viewer, Member, Admin and Owner are the install roles; a project grant can replace the install role for one project.
- Errors are JSON
{code, message, field?}with the codesunauthorized,forbidden,not_found,conflict,validation,rate_limited,unavailable(also read-only mode) andinternal. - Request bodies are capped at 1 MiB, except uploads. Unknown JSON fields are rejected.
- Every request that is not a GET writes an audit log entry. The Audit column names its action.
- Types named in the tables are the Go types in
pkg/api/types.go(MIT licensed), with camelCase JSON names. TypeScript types are generated from them.
System, auth, users
| Method | Path | Body and response | Role | Audit |
|---|---|---|---|---|
| GET | /healthz | 200 "ok" when the process runs | Public | |
| GET | /readyz | {version, ready, readOnly, checks{db,migrations,hub,agents}} | Public | |
| GET | /api/v1/version | {version, commit, date} | Public | |
| GET | /api/v1/setup | SetupStatus | Public | |
| POST | /api/v1/setup | SetupRequest -> Me (sets cookie) | Public | setup.complete |
| POST | /api/v1/auth/login | LoginRequest -> Me or {needTotp: true, ticket} | Public | auth.login |
| POST | /api/v1/auth/login/totp | {ticket, code} -> Me | Public | auth.login_totp |
| POST | /api/v1/auth/logout | -> 204 | Viewer | auth.logout |
| POST | /api/v1/auth/forgot | {email} -> 204 (always) | Public | auth.forgot |
| POST | /api/v1/auth/reset | {token, password} -> Me | Public | auth.reset |
| POST | /api/v1/auth/verify-email | {token} -> 204 | Public | auth.verify_email |
| GET | /api/v1/me | Me | Viewer | |
| PATCH | /api/v1/me | {name?, password?, currentPassword?} -> User | Viewer | me.update |
| POST | /api/v1/me/2fa/setup | -> {secret, otpauthUrl} / {code} -> {recoveryCodes} / {password, code} -> 204 | Viewer | me.2fa_setup |
| POST | /api/v1/me/2fa/enable | TOTPEnableRequest -> TOTPEnableResponse | Viewer | me.2fa_enable |
| POST | /api/v1/me/2fa/disable | TOTPDisableRequest -> 204 | Viewer | me.2fa_disable |
| GET | /api/v1/me/notification-prefs | []NotificationPref | Viewer | |
| PUT | /api/v1/me/notification-prefs | []NotificationPref -> []NotificationPref | Viewer | me.notification_prefs |
| GET | /api/v1/me/notifications | Page[Notification] (query before=) | Viewer | |
| POST | /api/v1/me/notifications/read | {ids[] or all} -> 204 | Viewer | |
| POST | /api/v1/cli/auth/start | -> CLIAuthStart | Public | cli_auth.start |
| POST | /api/v1/cli/auth/approve | {code} -> 204 | Viewer | cli_auth.approve |
| POST | /api/v1/cli/auth/poll | CLIAuthPoll -> CLIAuthPollResponse | Public | |
| GET | /api/v1/tokens | []APIToken | Viewer | |
| POST | /api/v1/tokens | CreateTokenRequest -> CreateTokenResponse | Viewer | token.create |
| DELETE | /api/v1/tokens/{id} | -> 204 | Viewer | token.delete |
| GET | /api/v1/members | []User | Viewer | |
| GET | /api/v1/invites | []Invite | Admin | |
| POST | /api/v1/invites | CreateInviteRequest -> Invite | Admin | invite.create |
| DELETE | /api/v1/invites/{id} | -> 204 | Admin | invite.delete |
| GET | /api/v1/invites/{id} | InvitePreview | Public | |
| POST | /api/v1/invites/accept | {token, email, name, password} -> Me | Public | invite.accept |
| PATCH | /api/v1/members/{id} | UpdateMemberRequest -> User | Admin | member.update |
| DELETE | /api/v1/members/{id} | 204 | Admin | member.delete |
| POST | /api/v1/members/{id}/transfer-ownership | {password, code?} -> 204 | Owner | member.transfer_ownership |
| GET | /api/v1/audit | Page[AuditEntry] (query before=&limit=) | Admin |
Install, settings, hosts, upgrades
| Method | Path | Body and response | Role | Audit |
|---|---|---|---|---|
| GET | /api/v1/install | Install | Viewer | |
| PATCH | /api/v1/install | UpdateInstallRequest -> Install (name, base domain, console domain, ACME email, trusted proxies, registry cap, build timeout default) | Admin | install.update |
| GET | /api/v1/settings/backups | BackupSettings | Admin | |
| PUT | /api/v1/settings/backups | BackupSettings -> BackupSettings | Admin | settings.backups_update |
| POST | /api/v1/settings/backups/test | -> {ok, error?} | Admin | settings.backups_test |
| GET | /api/v1/settings/smtp | SMTPSettings | Admin | |
| PUT | /api/v1/settings/smtp | SMTPSettings -> SMTPSettings | Admin | settings.smtp_update |
| POST | /api/v1/settings/smtp/test | {to} -> {ok, error?} | Admin | settings.smtp_test |
| GET | /api/v1/settings/alerts | InstallNotifications | Admin | |
| PUT | /api/v1/settings/alerts | InstallNotifications -> InstallNotifications | Admin | settings.alerts_update |
| POST | /api/v1/settings/recovery-key | {password} -> {recoveryKey} (audited) | Owner | settings.recovery_key_reveal |
| GET | /api/v1/hosts | []Host (with conflicts, reachability, usage) | Viewer | |
| POST | /api/v1/hosts/join-tokens | CreateJoinTokenRequest -> JoinToken | Admin | host.join_token |
| PATCH | /api/v1/hosts/{id} | UpdateHostRequest -> Host (name, roles, drain, reserve) | Admin | host.update |
| POST | /api/v1/hosts/{id}/maintenance | {on} -> Host | Admin | host.maintenance |
| POST | /api/v1/hosts/{id}/readopt | -> Host | Admin | host.readopt |
| DELETE | /api/v1/hosts/{id}/conflicts | Host | Admin | host.clear_conflicts |
| DELETE | /api/v1/hosts/{id} | -> 204 (refused while it runs replicas, unless ?force=1) (query force=1) | Admin | host.delete |
| GET | /api/v1/hosts/{id}/metrics | MetricsResponse (query range=&from=&until=) | Viewer | |
| POST | /api/v1/upgrade | UpgradeRequest -> UpgradeStatus | Admin | install.upgrade |
| GET | /api/v1/upgrade | UpgradeStatus | Viewer | |
| GET | /api/v1/registry-credentials | []RegistryCredential | Member | |
| POST | /api/v1/registry-credentials | CreateRegistryCredentialRequest -> RegistryCredential | Member | registry_credential.create |
| DELETE | /api/v1/registry-credentials/{id} | -> 204 (refused while a service uses it) | Member | registry_credential.delete |
| GET | /api/v1/restore/unknown-replicas | []UnknownReplica | Admin | |
| POST | /api/v1/restore/unknown-replicas/{id}/adopt | -> 204 | Admin | restore.adopt |
| POST | /api/v1/restore/unknown-replicas/{id}/remove | 204 | Admin | restore.remove |
| POST | /api/v1/restore/finish | 204 | Admin | restore.finish |
Projects, environments, canvas, changes
| Method | Path | Body and response | Role | Audit |
|---|---|---|---|---|
| GET | /api/v1/projects | []Project (query sort=activity|created|name) | Viewer | |
| POST | /api/v1/projects | CreateProjectRequest (name optional: a two-word name is generated) -> Project (with production) | Member | project.create |
| GET | /api/v1/projects/{pid} | Project | Viewer | |
| PATCH | /api/v1/projects/{pid} | UpdateProjectRequest -> Project | Member | project.update |
| DELETE | /api/v1/projects/{pid} | {confirm: "<name>"} -> 204 (stops everything, deletes volumes after 48 h) | Admin | project.delete |
| GET | /api/v1/projects/{pid}/members | []ProjectGrant | Viewer | |
| PUT | /api/v1/projects/{pid}/members | []ProjectGrant -> []ProjectGrant | Admin | project.grants_update |
| GET | /api/v1/projects/{pid}/usage | UsageResponse (query from=&until=) | Viewer | |
| POST | /api/v1/projects/{pid}/environments | CreateEnvironmentRequest -> Environment | Member | environment.create |
| PATCH | /api/v1/environments/{eid} | UpdateEnvironmentRequest (name, egress) -> Environment | Member | environment.update |
| DELETE | /api/v1/environments/{eid} | {confirm} -> 204 (not the last one) | Admin | environment.delete |
| POST | /api/v1/environments/{eid}/sync | {from: eid} -> ChangesResponse (staged, with tags) | Member | environment.sync |
| GET | /api/v1/environments/{eid}/canvas | Canvas | Viewer | |
| PUT | /api/v1/environments/{eid}/positions | SavePositionsRequest -> 204 (broadcast) | Member | |
| PUT | /api/v1/environments/{eid}/groups | []Group -> []Group | Member | canvas.groups_update |
| POST | /api/v1/environments/{eid}/presence | {cursor?} -> 204 | Viewer | |
| GET | /api/v1/environments/{eid}/changes | ChangesResponse | Viewer | |
| DELETE | /api/v1/environments/{eid}/changes | -> 204 | Member | changes.discard_all |
| DELETE | /api/v1/environments/{eid}/changes/{cid} | 204 | Member | changes.discard |
| POST | /api/v1/environments/{eid}/changes/commit | CommitRequest -> CommitResponse | Member | changes.commit |
| GET | /api/v1/environments/{eid}/activity | Page[Activity] (query service=&kind=&before=) | Viewer | |
| GET | /api/v1/commits/{id} | CommitDetail (message, author, full diff, secrets masked) | Viewer | |
| GET | /api/v1/events | Event (Server-Sent Events, query environment=) | Viewer | |
| GET | /api/v1/environments/{eid}/shared-variables | VariablesResponse | Viewer | |
| PUT | /api/v1/environments/{eid}/shared-variables | SetVariablesRequest -> VariablesResponse | Member | shared_variables.stage |
| POST | /api/v1/environments/{eid}/shared-variables/reveal | RevealRequest -> RevealResponse | Member | shared_variables.reveal |
| POST | /api/v1/environments/{eid}/shared-variables/share | {name, services[]} -> 204 (staged) | Member | shared_variables.share |
| GET | /api/v1/environments/{eid}/export | 5050.yaml text (manifest.ProjectFile) | Viewer | |
| POST | /api/v1/imports/railway | {token, projectName?} -> Import (creates a project with staged changes) | Member | import.railway |
| POST | /api/v1/environments/{eid}/imports/compose | YAML body -> Import (staged) | Member | import.compose |
| POST | /api/v1/environments/{eid}/services/{sid}/imports/heroku-env | text body -> Import (staged) | Member | import.heroku_env |
| GET | /api/v1/imports/{id} | Import with report | Member | |
| GET | /api/v1/search | SearchResult (query q=) | Viewer |
Services
| Method | Path | Body and response | Role | Audit |
|---|---|---|---|---|
| POST | /api/v1/environments/{eid}/services | CreateServiceRequest -> CreateServiceResponse | Member | service.create |
| GET | /api/v1/environments/{eid}/services/{sid} | Service (config with source map for file-set fields) | Viewer | |
| PATCH | /api/v1/environments/{eid}/services/{sid}/config | UpdateServiceConfigRequest -> Service (staged) | Member | service.config_stage |
| PATCH | /api/v1/environments/{eid}/services/{sid}/info | {name?, icon?} -> Service (rename staged, icon immediate) | Member | service.info_update |
| POST | /api/v1/environments/{eid}/services/{sid}/duplicate | -> Service (staged) | Member | service.duplicate |
| DELETE | /api/v1/environments/{eid}/services/{sid} | {confirm} -> 204 (staged) | Admin | service.delete |
| GET | /api/v1/environments/{eid}/services/{sid}/variables | VariablesResponse | Viewer | |
| PUT | /api/v1/environments/{eid}/services/{sid}/variables | SetVariablesRequest -> VariablesResponse | Member | variables.stage |
| POST | /api/v1/environments/{eid}/services/{sid}/variables/reveal | RevealRequest -> RevealResponse | Member | variables.reveal |
| GET | /api/v1/environments/{eid}/services/{sid}/deployments | []Deployment (query limit=&q=) | Viewer | |
| POST | /api/v1/environments/{eid}/services/{sid}/deploy | DeployRequest -> Deployment | Member | deployment.deploy |
| POST | /api/v1/environments/{eid}/services/{sid}/uploads | application/gzip -> UploadResponse (query message=) | Member | deployment.upload |
| GET | /api/v1/deployments/{did} | DeploymentDetail | Viewer | |
| POST | /api/v1/deployments/{did}/redeploy | -> Deployment | Member | deployment.redeploy |
| POST | /api/v1/deployments/{did}/rollback | Deployment | Member | deployment.rollback |
| POST | /api/v1/deployments/{did}/restart | Deployment | Member | deployment.restart |
| POST | /api/v1/deployments/{did}/abort | Deployment | Member | deployment.abort |
| POST | /api/v1/deployments/{did}/remove | Deployment | Member | deployment.remove |
| POST | /api/v1/replicas/{rid}/move | {hostId?} -> 204 (singleton move after confirm, 7.1) | Admin | replica.move |
| GET | /api/v1/deployments/{did}/build-logs | LogsResponse (query follow=1 (SSE of []LogLine)) | Viewer | |
| GET | /api/v1/logs | LogsResponse (query environment=&services=&deployment=&type=deploy,build,http&q=&since=&until=&limit=&around=) | Viewer | |
| GET | /api/v1/logs/stream | []LogLine (Server-Sent Events, query same as /logs) | Viewer | |
| GET | /api/v1/environments/{eid}/services/{sid}/metrics | MetricsResponse (query range=&from=&until=&view=sum|replica) | Viewer | |
| GET | /api/v1/environments/{eid}/services/{sid}/db-metrics | DBMetricsResponse (query range=) | Viewer | |
| GET | /api/v1/environments/{eid}/services/{sid}/monitors | []Monitor | Viewer | |
| POST | /api/v1/environments/{eid}/services/{sid}/monitors | CreateMonitorRequest -> Monitor | Member | monitor.create |
| PATCH | /api/v1/monitors/{id} | UpdateMonitorRequest -> Monitor | Member | monitor.update |
| DELETE | /api/v1/monitors/{id} | 204 | Member | monitor.delete |
| GET | /api/v1/environments/{eid}/services/{sid}/domains | []Domain | Viewer | |
| POST | /api/v1/environments/{eid}/services/{sid}/domains | CreateDomainRequest -> Domain | Member | domain.create |
| PATCH | /api/v1/domains/{id} | UpdateDomainRequest -> Domain | Member | domain.update |
| DELETE | /api/v1/domains/{id} | 204 | Member | domain.delete |
| POST | /api/v1/domains/{id}/check | -> Domain | Member | domain.check |
| POST | /api/v1/domains/{id}/retry-certificate | Domain | Member | domain.retry_certificate |
| POST | /api/v1/environments/{eid}/services/{sid}/tcp-proxies | CreateTCPProxyRequest -> TCPProxy | Member | tcp_proxy.create |
| DELETE | /api/v1/environments/{eid}/services/{sid}/tcp-proxies/{id} | 204 | Member | tcp_proxy.delete |
| POST | /api/v1/environments/{eid}/services/{sid}/volume | CreateVolumeRequest -> Volume | Member | volume.create |
| GET | /api/v1/environments/{eid}/services/{sid}/volume | VolumeDetail | Viewer | |
| PATCH | /api/v1/environments/{eid}/services/{sid}/volume | UpdateVolumeRequest -> Volume | Member | volume.update |
| DELETE | /api/v1/environments/{eid}/services/{sid}/volume | ConfirmRequest -> 204 | Admin | volume.delete |
| POST | /api/v1/environments/{eid}/services/{sid}/volume/wipe | ConfirmRequest -> 204 | Admin | volume.wipe |
| GET | /api/v1/environments/{eid}/services/{sid}/backups | BackupsResponse | Viewer | |
| POST | /api/v1/environments/{eid}/services/{sid}/backups | Backup | Member | backup.create |
| PUT | /api/v1/environments/{eid}/services/{sid}/backups/schedule | BackupSchedule -> BackupSchedule | Member | backup.schedule_update |
| POST | /api/v1/backups/{id}/lock | {locked} | Member | backup.lock |
| DELETE | /api/v1/backups/{id} | 204 | Admin | backup.delete |
| POST | /api/v1/environments/{eid}/services/{sid}/restore | RestoreRequest -> RestoreResponse | Admin | backup.restore |
| POST | /api/v1/environments/{eid}/services/{sid}/promote | PromoteRequest -> 204 | Admin | backup.promote |
| POST | /api/v1/environments/{eid}/services/{sid}/major-upgrade | MajorUpgradeRequest -> RestoreResponse | Admin | database.major_upgrade |
| GET | /api/v1/environments/{eid}/services/{sid}/connect-info | ConnectInfo | Member | |
| POST | /api/v1/environments/{eid}/services/{sid}/regenerate-credentials | CommitResponse | Admin | database.regenerate_credentials |
| GET | /api/v1/environments/{eid}/services/{sid}/data | DataResponse | Member | |
| GET | /api/v1/environments/{eid}/services/{sid}/extensions | []Extension | Member | |
| POST | /api/v1/environments/{eid}/services/{sid}/extensions | EnableExtensionRequest -> Extension | Admin | database.extension_enable |
| GET | /api/v1/environments/{eid}/services/{sid}/redis/keys | RedisKeysPage (query match=&cursor=) | Member | |
| POST | /api/v1/environments/{eid}/services/{sid}/redis/keys/reveal | RedisRevealRequest -> RedisRevealResponse | Member | database.redis_reveal |
| GET | /api/v1/environments/{eid}/services/{sid}/cron-runs | []CronRun | Viewer | |
| POST | /api/v1/environments/{eid}/services/{sid}/cron-runs | CronRun | Member | cron.run_now |
| GET | /api/v1/environments/{eid}/services/{sid}/shell | 204 (WebSocket, query replica=&cols=&rows=&session=) | Member | service.shell |
| GET | /api/v1/environments/{eid}/services/{sid}/tunnel | 204 (WebSocket, query port=) | Member | service.tunnel |
Templates, GitHub, webhooks
| Method | Path | Body and response | Role | Audit |
|---|---|---|---|---|
| GET | /api/v1/templates | []TemplateSummary (query q=) | Viewer | |
| GET | /api/v1/templates/{id} | TemplateDetail (services, inputs with generated defaults) | Viewer | |
| POST | /api/v1/environments/{eid}/templates/{id}/deploy | {inputs} -> TemplateDeployResponse | Member | template.deploy |
| GET | /api/v1/icons/{name} | SVG/PNG icons for templates, sources and the devicon picker | Public | |
| GET | /api/v1/github | GitHubStatus | Viewer | |
| POST | /api/v1/github/app | {owner?: "org", returnTo?} -> {formUrl, manifest} | Admin | github.app_create |
| GET | /api/v1/github/app/callback | 204 (302 redirect, query code=) | Admin | github.app_callback |
| GET | /api/v1/github/repos | []GitHubRepo (query q=&refresh=1) | Member | |
| GET | /api/v1/github/branches | []string (query repo=) | Member | |
| POST | /api/v1/github/scan | ScanRequest -> ScanResult (builder, start command, config files, packages, variable names, port) | Member | github.scan |
| POST | /api/v1/github/webhook | GitHub delivery (signature checked) | Public | github.webhook |
| GET | /api/v1/projects/{pid}/webhooks | []Webhook | Admin | |
| POST | /api/v1/projects/{pid}/webhooks | Webhook -> Webhook | Admin | webhook.create |
| PATCH | /api/v1/webhooks/{id} | Webhook -> Webhook | Admin | webhook.update |
| DELETE | /api/v1/webhooks/{id} | 204 | Admin | webhook.delete |
| POST | /api/v1/webhooks/{id}/test | -> {status, responseCode} | Admin | webhook.test |
| POST | /api/v1/join | 204 | Public | agent.join |
| GET | /api/v1/connect | 204 (WebSocket) | Public | agent.connect |
| GET | /api/v1/uploads/{id} | application/gzip | Public |
Agent endpoints
Agents call these. They are also served on agents.<console domain> so you can firewall them separately. See Agent protocol.
| Method | Path | Auth |
|---|---|---|
| POST | /api/agent/v1/join | join token in body (rate limited 10 per minute per IP) |
| GET (WebSocket) | /api/agent/v1/connect | host token bound to machine-id and WireGuard key |
| GET | /api/agent/v1/uploads/{id} | host token; serves a 5050 up tarball to the build host |
Next steps
- CLI overview: the CLI calls these endpoints for you.
- Security model: tokens, roles and the audit log.