Skip to content

API Endpoints

All endpoints are served from the control plane on port 3001 (HTTP) and 3002 (gRPC). Fabric also provides a GraphQL API at /graphql — see GraphQL API below.

MethodPathDescription
GET/healthzHealth check
GET/readyzReadiness check
GET/openapi.jsonOpenAPI specification
MethodPathDescription
POST/v1/auth/signupSign up with email/password
POST/v1/auth/loginLog in with email/password
POST/v1/auth/logoutLog out (revoke current token)
POST/v1/auth/logout-allInvalidate all sessions
POST/v1/auth/token/refreshRefresh access token (single-use rotation)
POST/v1/auth/social-loginConsumer-driven social login
GET/v1/auth/verifyVerify email address
POST/v1/auth/resend-verificationResend verification email
POST/v1/auth/forgot-passwordSend password reset email
POST/v1/auth/reset-passwordReset password with token
POST/v1/auth/change-passwordChange password (requires auth)
GET/v1/auth/social/{provider}Initiate server-side social login
GET/v1/auth/callbackSocial login OAuth callback
MethodPathDescription
GET/v1/meCurrent principal
GET/v1/me/organizationsMy organizations
GET/v1/me/teamsMy teams
GET/v1/me/permissionsEffective permissions
GET/v1/me/social-connectionsConnected social providers
DELETE/v1/me/social-connections/{provider}Disconnect a social provider
MethodPathDescription
GET/v1/admin/usersList all users
GET/v1/admin/users/{id}Get user details
DELETE/v1/admin/users/{id}Soft-delete a user
POST/v1/admin/users/{id}/unlockUnlock locked account
POST/v1/admin/users/{id}/verifyForce-verify email
POST/v1/admin/users/{id}/logout-allInvalidate all sessions for user
MethodPathDescription
POST/v1/organizationsCreate organization
GET/v1/organizations/{id}Get organization
GET/v1/organizations/{id}/teamsList teams
GET/v1/organizations/{id}/membersList members
POST/v1/teamsCreate team (RBAC enforced)
GET/v1/teams/{id}Get team
MethodPathDescription
POST/v1/invitationsCreate invitation (Admin+, duplicate/rate-limit guarded)
GET/v1/invitationsList invitations for org (?organization_id=)
GET/v1/invitations/{id}Get invitation by ID
GET/v1/invitations/{id}/acceptAccept invitation (token verified, creates membership)
POST/v1/invitations/{id}/revokeRevoke invitation
MethodPathDescription
GET/v1/organizations/{id}/settingsGet org settings (branding, rate limits)
PUT/v1/organizations/{id}/settingsUpdate org settings (Owner only)
MethodPathDescription
POST/v1/authz/checkSingle permission check
POST/v1/authz/check-batchBatch permission check
MethodPathDescription
POST/v1/jobsSubmit a job (with idempotency key, cost estimate)
GET/v1/jobs/{id}Get job by canonical job_id
GET/v1/jobsList jobs
GET/v1/jobs/{id}/usageJob cost/usage roll-up
GET/v1/jobs/{id}/eventsPer-job event stream (SSE)
MethodPathDescription
POST/v1/workflow-definitionsCreate definition (supports NodeDefinition schema)
GET/v1/workflow-definitionsList definitions
POST/v1/workflow-runsCreate run (with idempotency key)
GET/v1/workflow-runs/{id}Get run status
POST/v1/workflow-runs/{id}/startStart execution
POST/v1/workflow-runs/{id}/cancelCancel run
GET/v1/workflow-runs/{id}/eventsPer-run event stream (SSE)

POST /v1/workflows/runs accepts request bodies in JSON, YAML, or TOML, selected by the Content-Type header (plan 077). JSON is the default when the header is missing or unrecognised, so existing clients are unaffected.

HeaderParser
application/json (default)serde_json
application/yaml / text/yaml / application/x-yamlserde_yaml_ng
application/toml / text/toml / application/x-tomltoml

Response bodies remain JSON. See the Submitting Jobs guide for usage examples.

MethodPathDescription
GET/v1/providersList available providers and capabilities
POST/v1/providers/executeExecute a provider request
POST/v1/providers/execute/streamExecute with SSE token streaming
POST/v1/providers/estimateCost estimation
MethodPathDescription
POST/v1/api-keysCreate key (returns raw key once)
GET/v1/api-keysList keys
GET/v1/api-keys/{id}Get key metadata
DELETE/v1/api-keys/{id}Revoke key
POST/v1/api-keys/{id}/disableDisable key
MethodPathDescription
POST/v1/assetsUpload asset
GET/v1/assets/{id}Download asset
MethodPathDescription
GET/v1/organizations/{id}/usageUsage summary with breakdowns
GET/v1/organizations/{id}/usage/recordsDetailed usage records
MethodPathDescription
GET/v1/organizations/{id}/audit-logsOrg audit trail
GET/v1/audit-logsGlobal audit logs
MethodPathDescription
GET/v1/events/streamAll events (SSE)
GET/v1/events/wsAll events (WebSocket)
GET/v1/jobs/{id}/eventsPer-job events (SSE)
GET/v1/workflow-runs/{id}/eventsPer-run events (SSE)

Fabric provides a full GraphQL API alongside REST, enabled with --features graphql. All GraphQL operations enforce the same authentication, RBAC, ACL, rate limiting, and audit logging as the REST API.

MethodPathDescription
POST/graphqlQuery and mutation endpoint
GET/graphqlGraphiQL playground (dev mode only)
GET/graphql/sdlSDL schema export (dev mode only)
GET/graphql/wsWebSocket subscriptions (graphql-ws protocol)
QueryDescription
organization(id)Get organization by ID
organizations(first, after)List organizations (paginated)
team(id)Get team by ID
teams(orgId, first, after)List teams in an organization
meCurrent authenticated principal
myOrganizationsOrganizations the caller belongs to
myTeamsTeams accessible to the caller
myPermissionsEffective permissions (highest role per scope)
apiKey(id)Get API key metadata
apiKeys(orgId, first)List API keys for an organization
workflows(orgId, first)List registered workflows
workflow(name, orgId)Resolve workflow by name
workflowRun(id)Get workflow run status
workflowRuns(orgId, first)List workflow runs
waitingRuns(orgId, first)List runs waiting for signals
asset(id)Get asset metadata
assets(orgId, first)List assets
assetDownloadUrl(id, ttlSeconds)Generate signed download URL
webhook(id)Get webhook
webhooks(orgId, first)List webhooks
webhookDeliveries(webhookId, first)List delivery attempts
MutationDescription
createOrganization(name, slug)Create organization (caller becomes Owner)
updateOrganization(id, name)Update organization name
archiveOrganization(id)Archive organization (soft-delete)
createTeam(orgId, name, slug)Create team within organization
disableApiKey(id)Disable an API key
deleteApiKey(id)Permanently delete an API key
submitWorkflowRun(name, orgId, input)Submit a workflow run
cancelWorkflowRun(id, reason)Cancel a running workflow
pauseWorkflowRun(id, reason)Pause a workflow
resumeWorkflowRun(id)Resume a paused workflow
signalWorkflowRun(id, signalName, payload)Send signal to a waiting workflow
approveWorkflowRun(id, approved, reason)Approve or reject a waiting workflow
createWebhook(input)Create webhook subscription
deleteWebhook(id)Delete webhook
SubscriptionDescription
events(orgId)All events for an organization
workflowRunEvents(runId)Events for a specific workflow run

The GraphQL API enforces all the same security controls as REST:

  • Authentication: JWT or API key via Authorization header
  • RBAC + ACL: Every resolver checks evaluate_with_acls() (3-layer: deny ACL > allow ACL > role hierarchy)
  • API key scopes: Validated per-resolver when using API key auth
  • Rate limiting: Same per-tenant + per-org limits as REST
  • Depth limit: Max 10 levels of nesting
  • Complexity limit: Max cost 200 (list fields multiply by page size)
  • Pagination: All list fields require first (max 100)
  • Query timeout: 30 seconds
  • Batch rejection: Array-batched requests ([{query:...}]) are rejected
  • CSRF: Rejects non-JSON Content-Type
  • Introspection: Disabled in production
  • Audit: All mutations logged with transport: "graphql"
{
me {
principalId
authenticated
}
organizations(first: 10) {
id
name
slug
teams(first: 5) {
id
name
}
}
}
mutation {
createOrganization(name: "Acme Corp") {
id
name
slug
createdAt
}
}

GraphQL uses its own response format (not the REST envelope):

{
"data": { ... },
"errors": null,
"extensions": {
"requestId": "uuid"
}
}

Every response follows the standard envelope format:

{
"meta": {
"request_id": "uuid",
"trace_id": "uuid",
"timestamp": "2026-03-19T12:00:00Z",
"status": 200,
"version": "1.0"
},
"context": {
"principal_id": "uuid",
"organization_id": "uuid",
"team_id": null
},
"data": { ... },
"error": null,
"links": { ... }
}

Error responses:

{
"meta": { "status": 403, ... },
"data": null,
"error": {
"code": "forbidden",
"message": "Insufficient permissions"
}
}