Conventions
The request format, ids and slugs, return shapes, errors, paging and subscriptions, once, so the domain pages do not repeat them.
Requests
A POST to /api/graphql with Content-Type: application/json and a body of { "query": "...", "variables": { ... } }. Any other content type is refused with 415. GET serves GraphiQL to a browser and accepts a query in the URL.
Every example in this reference is a bare document with inline values, so it pastes into GraphiQL or a curl body as is. In real code, send values as variables:
{
"query": "mutation Redeploy($id: String!) { redeploy(appId: $id) { id status } }",
"variables": { "id": "prj_9f1c2ab7d3e4f5a6" }
}The schema itself is served by introspection at the endpoint, and published as schema.graphql at the root of the DeploCloud/deplo repository.
Ids and slugs
Every entity has an opaque id with a type prefix: prj_ for an app, db_ for a database, srv_ for a server, dpl_ for a deployment, fld_ for a folder, prc_ for a project, environ_ for an environment, dom_ for a domain, tok_ for a token, team_ for a team. Apps, teams, projects and environments also have a slug, unique inside their parent, which is what app(slug:) and X-Deplo-Team take. The ids in the examples are made up.
Return shapes
- A mutation returns the entity it changed, so a client needs no second fetch.
- Deletes and toggles return
Boolean. Bulk operations returnInt, the number affected. - A reveal returns a
String:revealConnection,rotateDatabasePassword,revealAppDeployHook,revealBasicAuthPassword,revealRegistrationLink. Reveals are mutations, never queries, so nothing caches or prefetches a secret. - A few operations that only read are mutations anyway, because they dial a server:
serverCertificates,serverCertificateAccounts,panelHttps,panelDns,checkServerHostInfo,checkServerReadiness,testDestination.
A verdict is a return value, not an error
Where an operation asks another system whether something works, the answer is in the payload and a failure resolves normally: testDestination answers report.ok: false, checkServerHealth answers a server with status: error. A client that treats "the request succeeded" as "the thing it tested works" reports success over a failed check.
Errors
Errors come back in the standard errors[] array. The message is safe to show a user: You don't have permission to deploy, Not authorized to resolve deleteApp, An API token can't access your account settings. Internal errors are masked; a stack trace never leaks.
{
"data": { "deleteApp": null },
"errors": [{ "message": "You don't have permission to delete apps", "path": ["deleteApp"] }]
}Validation happens after authorization: a caller refused for the wrong permission is refused before an argument is read.
Lists and paging
Lists come back whole, newest first unless the page says otherwise, filtered to the active team. Two reads look further:
activitypages with a cursor: pass the last row'scursorback ascursorfor the next page, and cap a page withlimit.searchis the one read that spans every team the caller can reach. Everything else is scoped to the active team.
Subscriptions
Five subscriptions stream over Server-Sent Events, not WebSockets. Each fires once immediately with the current snapshot, then on every change, so a client tracks state with no polling.
curl -N https://deplo.example.com/api/graphql \
-H "Authorization: Bearer deplo_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Accept: text/event-stream" \
-H "Content-Type: application/json" \
-d '{"query":"subscription { appStatus(slug: \"shop\") { status latestDeployment { status } } }"}'| Subscription | Emits | Page |
|---|---|---|
appStatus(slug) | The app, on every power or deployment change | Apps |
databaseStatus(id) | The database, on every status change | Databases |
activeDeployments | How many deployments are in flight in the team | Deployments |
activeMigration | The migration in flight, or the finished run until its report is closed | Migration |
dockerCleanupRuns | The whole cleanup history, on every change | Docker cleanup |
See also
Did this page help you?