API

The GraphQL API behind the dashboard, with an interactive playground.

Everything the dashboard and the CLI do goes through one GraphQL API at https://lucity.cloud/graphql, which you can call yourself. The playground documents every query, mutation and type.

Authentication

Every request carries an access token as a bearer token. The CLI prints one for your session and the active workspace:

Request
curl https://lucity.cloud/graphql \
  -H "Authorization: Bearer $(lucity token)" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ project(id: \"zeitlos-software/vouch\") { name environments { name } } }"}'
Response
{
  "data": {
    "project": {
      "name": "vouch",
      "environments": [
        {
          "name": "development"
        },
        {
          "name": "production"
        }
      ]
    }
  }
}

For automation, use a workspace API token. The API doesn't accept the lucity_… value itself, so let the CLI exchange it. With the token in LUCITY_API_TOKEN, lucity token prints an access token that carries the API token's role:

Request
export LUCITY_API_TOKEN=lucity_…
curl https://lucity.cloud/graphql \
  -H "Authorization: Bearer $(lucity token)" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ projects { id } }"}'

Access tokens are short-lived, so fetch a new one for every run instead of storing it. A token also decides the workspace, and every request runs against the workspace its token belongs to.

Playground

lucity.cloud/playground(opens in a new tab) is an interactive editor for the API, with autocomplete as you type. The book icon in its sidebar opens the documentation, which describes every query, mutation and type, so it doubles as the API reference.

To run queries against your workspace, add your token in the Headers tab as {"Authorization": "Bearer …"}.

Ids

Resources are addressed by ids that start with the workspace, and each kind of id has its own scalar type:

ScalarFormatExample
ProjectIDworkspace/projectzeitlos-software/vouch
EnvironmentIDworkspace/project/environmentzeitlos-software/vouch/production
ServiceIDworkspace/project/environment/servicezeitlos-software/vouch/production/vouch
DatabaseIDworkspace/project/environment/databasezeitlos-software/vouch/production/feedback

Key-value stores, buckets and volumes follow the same pattern as databases. Unlike the CLI, the API always takes the full id.

Roles

Every token carries a role, and it can only call the operations that role allows:

RoleWho has it
AdminWorkspace admins, and API tokens created with the admin role
MemberWorkspace members, and API tokens created with the member role
DeployerKeyless GitHub Actions sessions

Members and roles describes what each role can do.

Errors

A failed operation still answers with HTTP 200. The reason is in the errors list, next to whatever data could be returned:

Response
{
  "errors": [
    {
      "message": "project with id \"zeitlos-software/nope\" not found",
      "path": [
        "project"
      ],
      "locations": [
        {
          "line": 1,
          "column": 3
        }
      ]
    }
  ],
  "data": null
}

Live logs

Logs stream as GraphQL subscriptions over a WebSocket at wss://lucity.cloud/graphql, using the graphql-transport-ws protocol. Put the token in the connection_init payload:

{ "type": "connection_init", "payload": { "Authorization": "Bearer <token>" } }

Any client that speaks the protocol works, such as graphql-ws(opens in a new tab) for JavaScript.