Control API reference¶
Astrolift's typed control-plane API is GraphQL. Focused REST, SSE, and WebSocket routes exist where device authentication, callbacks, streaming, or CI semantics do not fit GraphQL well.
Base URLs¶
Given an install at https://astrolift.example.com:
| Surface | URL |
|---|---|
| GraphQL HTTP/explorer | https://astrolift.example.com/app/gql/config/ |
| GraphQL subscriptions | wss://astrolift.example.com/app/gql/config/ws/ |
| CLI device flow | https://astrolift.example.com/api/cli/v1/auth/... |
| MCP | https://astrolift.example.com/api/mcp/v1/ |
| Health | https://astrolift.example.com/health/ |
The server root returns a link map when requested as JSON:
Authentication and tenancy¶
User API tokens start with alft_at_. App-scoped deploy tokens start with
alft_dt_ and are accepted only by their intended CI/deploy routes.
Authorization: Bearer alft_at_...
X-Astrolift-Organization: <organization-guid>
Content-Type: application/json
The organization header selects one organization when the identity belongs to more than one. Never use a slug where the API requires a GUID. The token's scopes narrow the user's RBAC grants; requests must pass both checks.
Current API-token scopes are read:apps, write:apps, read:clusters,
agent-env-spec:write, secret:read, secret:write, mcp:read,
mcp:dispatch, mcp:write, and admin. Use the smallest set that supports
the integration.
GraphQL request¶
curl -sS https://astrolift.example.com/app/gql/config/ \
-H "Authorization: Bearer $ASTROLIFT_TOKEN" \
-H "X-Astrolift-Organization: $ASTROLIFT_ORG_ID" \
-H 'Content-Type: application/json' \
--data-binary @- <<'JSON'
{
"query": "query { astroliftServerInfo { version serverTime capabilities } }",
"variables": {}
}
JSON
A successful HTTP response can still contain GraphQL errors; check that
array before reading data. Mutations generally return an envelope with
ok, structured errors, and data. Do not treat HTTP 200 as mutation
success without checking ok.
The installation's explorer and introspection expose the exact schema supported
by that server. The platform repository also publishes schema.graphql for
client generation. Prefer generated types or committed operations over building
query strings from user input.
Generated contracts and drift checks¶
The release source publishes the GraphQL SDL
and the MCP capability superset.
Replace main in those URLs with an immutable backend tag or commit SHA when
pinning a client build.
Platform contributors regenerate both artifacts with make contracts and
verify them with make contracts-check. CI assembles the full-feature
Strawberry schema, byte-compares the backend/frontend SDL, validates every MCP
input JSON Schema, checks MCP metadata against live handlers, regenerates
frontend GraphQL types, and rejects any diff.
This is not yet a generated catch-all OpenAPI document. Most focused REST routes still define payloads imperatively, so route introspection would publish names without truthful request, response, and authorization schemas. REST OpenAPI will be generated as those endpoints adopt shared typed contracts.
Compatibility¶
- Query server capabilities before assuming an optional module exists.
- Additive GraphQL fields are backward compatible; clients should ignore response fields they do not understand.
- Pin a CLI/SDK version in unattended automation.
- Use idempotency keys on deploy routes when retrying after a network failure.
- Expect
401for invalid/expired credentials and permission errors when RBAC or the token scope ceiling denies the action.
There is no single catch-all REST/OpenAPI surface for control-plane CRUD. Use GraphQL unless a documented workflow explicitly names a REST, SSE, or WebSocket route. This avoids depending on internal Django paths.
Secrets¶
Secret-list operations return names, references, and presence metadata. A
caller needs secret:read plus secret.read RBAC to reveal a value on the few
surfaces that support reveal. secret:write permits write-through operations,
not readback. MCP intentionally never exposes secret values.