GraphQL API
Everything the FluidGrids app, CLI, SDKs and MCP server do goes through one GraphQL API on the Burdenoff Workspaces platform. Every operation is authenticated and permission-checked against the caller's roles in the workspace, so a script can never do more than its user or app could do in the app.
The Node SDK and the CLI wrap this API and set the headers below for you. Use the API directly when neither fits.
Endpoints
FluidGrids is a workspace product, so its operations are on the workspace gateway. Sign-in, organisations and billing are on the global gateway.
| Environment | Workspace gateway | Global gateway |
|---|---|---|
| Production | https://graphqlworkspaces.burdenoff.com/workspaces/graphql | https://graphql.burdenoff.com/global/graphql |
| Alpha | https://alphagraphqlworkspaces.burdenoff.com/workspaces/graphql | https://alphagraphql.burdenoff.com/global/graphql |
Headers
| Header | Value |
|---|---|
Authorization | Bearer <access token>, the platform token from sign-in |
X-Workspace-Authorization | Bearer <workspace token>, the token issued for the workspace you are acting in |
x-workspace-id | The workspace ID. Optional when you send the workspace token, which already names the workspace |
Origin | https://app.fluidgrids.ai (production) or https://alphaapp.fluidgrids.ai (alpha) |
The workflow operations are product-scoped: the gateway works out which product a request is for from its Origin header. Browsers send it automatically, but server-side clients (curl, Node, Python) do not, so set it yourself. Without it, workflow operations fail with BAD_USER_INPUT on the product context.
Get tokens through any platform sign-in flow: the device-code flow the CLI uses, PKCE for your own app, or client credentials for automation. See platform authentication.
curl https://graphqlworkspaces.burdenoff.com/workspaces/graphql \
-H "Authorization: Bearer $FG_ACCESS_TOKEN" \
-H "X-Workspace-Authorization: Bearer $FG_WORKSPACE_TOKEN" \
-H "x-workspace-id: $FG_WORKSPACE_ID" \
-H "Origin: https://app.fluidgrids.ai" \
-H "Content-Type: application/json" \
-d '{"query":"{ workflowDefinitions(input: { latestOnly: true, limit: 5 }) { items { workflowKey version status } total } }"}'
Main types
| Type | What it is |
|---|---|
WorkflowDefinition | One version of a workflow: workflowKey, version, name, status, isActive, definitionJson (the graph), tags, runs |
WorkflowRun | One execution: status, mode (TEST or PRODUCTION), progress, triggerData, startedAt, completedAt, duration, errorMessage, nodeStates, and parent and child runs for sub-workflows |
NodeState | The state of one node in a run |
WorkflowExecutionLog | One line of a run's log |
EventRegistration | A webhook or app-event trigger bound to a workflow |
WorkflowHumanRequest | A run waiting for a person to approve, decline or answer |
Example queries
List the latest version of every workflow:
query ListWorkflows {
workflowDefinitions(input: { latestOnly: true, limit: 20 }) {
items {
id
name
workflowKey
version
status
isActive
totalVersions
}
total
hasMore
}
}
Read a run with the state of each node:
query RunDetail($id: ID!) {
workflowRun(id: $id) {
id
workflowKey
version
status
progress
startedAt
completedAt
errorMessage
nodeStates {
id
nodeId
nodeType
status
}
}
}
Example mutations
Trigger a version through its manual trigger node. Pass an idempotencyKey so a retried request returns the original run instead of starting a second one:
mutation TriggerWorkflow {
triggerWorkflow(
input: {
workflowKey: "order-to-cash"
version: "3"
triggerNodeId: "trigger-1"
triggerData: { orderId: "ORD-12345" }
idempotencyKey: "ORD-12345"
}
) {
runId
status
version
}
}
Other frequently used operations: activateWorkflowDefinition, deactivateWorkflowDefinition, restoreWorkflowVersion, duplicateWorkflow, importWorkflowTemplate, cancelWorkflowRun, pauseWorkflowRun, resumeWorkflowRun, retryNode and workflowRunLogs. Each needs the permission listed in Permissions and Access Control; for example, activating needs Editor on workflow, and retrying a node needs Editor on node-state.
Subscriptions
Follow a run live over a WebSocket (graphql-ws protocol, same URL with wss://):
subscription FollowRun($runId: String!) {
workflowRunUpdated(runId: $runId) {
id
status
progress
}
}
Also available: nodeStateUpdated(runId), runLogAppended(runId), workflowCompleted(runId) and workflowError(runId).
Errors
| Code | Meaning |
|---|---|
FORBIDDEN | The token is missing or expired, your roles do not grant the action, or a required header such as x-workspace-id is missing. The message says which. |
BAD_USER_INPUT | The input is invalid, or the request has no product context (see the Origin header above). |
QUOTA_EXHAUSTED (HTTP 429) | The request would exceed a plan quota. See Plans and Quotas. |
Discover the schema
Introspection is disabled on the public gateways. The types above cover the FluidGrids part of the schema; the Node SDK exports TypeScript types for every operation it wraps.