Overview
CLAiRE exposes two API surfaces from the same process:
- GraphQL at
/graphql— the primary application API. Records, flows, agents, audit logs, and tenant administration all live here. - REST — a deliberately small surface for endpoints that don't fit GraphQL: liveness, SAML/SSO callbacks, MCP transport.
CSRF protection is applied to all API calls (except when running under Cypress). All endpoints that read or mutate tenant data require an authenticated session established via SSO.
REST API (OpenAPI 3.1.0)
The complete machine-readable specification is at the bottom of this page. The table below is a hand-curated index of every REST route, grouped by tag.
Health
| Method | Path | Summary | Source |
|---|---|---|---|
| GET | /api/health | Liveness probe — returns 200 with body "success". | app/modules/core/server-ts/app.ts |
MCP
| Method | Path | Summary | Source |
|---|---|---|---|
| POST | /mcp | Initialize MCP session or invoke a tool on an existing session. | app/modules/mcp/server-ts/index.ts |
| GET | /mcp | Open the server-to-client SSE stream for an MCP session. | app/modules/mcp/server-ts/index.ts |
| DELETE | /mcp | Terminate an MCP session. | app/modules/mcp/server-ts/index.ts |
SSO
| Method | Path | Summary | Source |
|---|---|---|---|
| GET | /login/sso | Begin SAML SSO — redirects browser to the IdP AuthnRequest. | app/modules/auth/server-ts/sub-modules/sso/index.ts |
| GET | /esign/sso | SAML step-up for an electronic signature (forces re-auth). | app/modules/auth/server-ts/sub-modules/sso/index.ts |
| POST | /login/callback | SAML Assertion Consumer Service — validates IdP response. | app/modules/auth/server-ts/sub-modules/sso/index.ts |
| GET | /logout/slo | Begin SAML Single Logout — destroys session, redirects to IdP. | app/modules/auth/server-ts/sub-modules/sso/index.ts |
| POST | /logout/callback | SAML SLO callback (HTTP-POST binding). | app/modules/auth/server-ts/sub-modules/sso/index.ts |
| GET | /logout/callback | SLO callback for IdPs that use HTTP-Redirect (e.g. Azure). | app/modules/auth/server-ts/sub-modules/sso/index.ts |
| GET | /azureb2c/callback | Azure B2C OIDC callback — returns an HTML completion shim. | app/modules/auth/server-ts/sub-modules/sso/index.ts |
SSO Hooks
| Method | Path | Summary | Source |
|---|---|---|---|
| GET | /okta/hooks | Okta inline-hook verification challenge. | app/modules/auth/server-ts/sub-modules/sso/index.ts |
| POST | /okta/hooks | Receive an Okta inline-hook event. | app/modules/auth/server-ts/sub-modules/sso/index.ts |
GraphQL endpoint
Almost everything other than the routes above is GraphQL. The endpoint is mounted at /graphql by Apollo Server and accepts both queries and mutations. File uploads use the graphql-upload multipart spec.
- Authentication — session cookie (
sessionId), established via SAML SSO. CSRF token required for mutations. - Authorization — per-operation, attribute-based. Resolvers check the caller's role, the record's classification tier, and the caller's clearance.
- Rate limiting — the website rate-limiter applies; sustained abuse returns HTTP 429.
- GraphiQL — the interactive explorer is exposed at
/graphiqlin development builds only.
app/modules/…/server-ts/graphql/. Run the dev server and open /graphiql for a complete, always-current reference.Model Context Protocol
CLAiRE speaks the Model Context Protocol over a Streamable-HTTP transport at /mcp. A client opens a session with a POST (no mcp-session-id header), the server returns a session id, and subsequent JSON-RPC calls echo that id. Long-running calls are delivered as server-sent events.
Lifecycle:
POST /mcpwithoutmcp-session-id— creates a session.POST /mcpwithmcp-session-id— sends a JSON-RPC request on that session.GET /mcpwithmcp-session-id— opens the server-to-client SSE stream.DELETE /mcpwithmcp-session-id— terminates the session.
Raw OpenAPI YAML
Paste this into any OpenAPI-compatible tool (Swagger UI, Redoc, Postman, Stoplight) for an interactive reference. The spec is also available as a download in the sidebar.
openapi: 3.1.0
info:
title: CLAiRE Platform REST API
version: 4.0.0
summary: HTTP/REST endpoints exposed by CLAiRE V4.
description: |
CLAiRE's primary application API is GraphQL (served at `/graphql`).
This document covers only the small set of true HTTP/REST endpoints:
health, the Model Context Protocol (MCP) transport, and the SAML / SSO
callback surface. GraphQL operations are not described here.
All endpoints are served from the same Express application defined in
`app/modules/core/server-ts/app.ts`. The SSO endpoints are only mounted
when `settings.sso.enabled` is true.
contact:
name: ComplianceG Labs
url: https://www.complianceg.com/get-in-touch/
servers:
- url: https://{host}
description: Tenant deployment (cloud or on-prem)
variables:
host:
default: app.example.com
description: Hostname of the CLAiRE deployment.
tags:
- name: Health
description: Liveness probes for orchestrators and uptime monitors.
- name: MCP
description: Model Context Protocol transport endpoints.
- name: SSO
description: SAML 2.0 single sign-on and single logout endpoints.
- name: SSO Hooks
description: Inline hooks invoked by identity providers (e.g. Okta).
paths:
/api/health:
get:
tags: [Health]
summary: Liveness probe.
description: |
Returns 200 OK with the literal body `success` when the application
process is reachable. Does NOT verify database, session-store, or
downstream connectivity — it is purely a liveness signal for Azure
and similar orchestrators.
operationId: getHealth
responses:
'200':
description: Application process is alive.
content:
text/plain:
schema:
type: string
example: success
/mcp:
post:
tags: [MCP]
summary: Initialize an MCP session or invoke a tool on an existing session.
description: |
Streamable-HTTP transport for the Model Context Protocol. The first
request omits the `mcp-session-id` header; the server creates a new
session and returns its id in the response headers. Subsequent
requests on the same session must echo that id.
operationId: mcpInvoke
parameters:
- $ref: '#/components/parameters/McpSessionId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/JsonRpcRequest'
responses:
'200':
description: JSON-RPC response or streamed server message.
content:
application/json:
schema:
$ref: '#/components/schemas/JsonRpcResponse'
text/event-stream:
schema:
type: string
description: Server-sent events stream for long-running calls.
'404':
description: `mcp-session-id` was supplied but no such session exists.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'500':
$ref: '#/components/responses/InternalError'
get:
tags: [MCP]
summary: Open the server-to-client SSE stream for an existing MCP session.
operationId: mcpStream
parameters:
- $ref: '#/components/parameters/McpSessionIdRequired'
responses:
'200':
description: Server-sent events stream of MCP messages.
content:
text/event-stream:
schema:
type: string
'400':
description: Missing or unknown `mcp-session-id` header.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
delete:
tags: [MCP]
summary: Terminate an MCP session.
operationId: mcpClose
parameters:
- $ref: '#/components/parameters/McpSessionId'
responses:
'200':
description: Session terminated (or no-op if no matching session).
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
const: true
/login/sso:
get:
tags: [SSO]
summary: Begin SAML SSO authentication.
description: |
Validates the SSO request, then redirects the browser to the tenant's
configured Identity Provider AuthnRequest endpoint. Mounted only when
`settings.sso.enabled` is true.
operationId: ssoLogin
parameters:
- $ref: '#/components/parameters/TenantCode'
- $ref: '#/components/parameters/EmailHint'
responses:
'302':
description: Redirect to the IdP AuthnRequest URL.
headers:
Location:
schema: { type: string, format: uri }
/esign/sso:
get:
tags: [SSO]
summary: Begin SAML step-up authentication for an electronic signature.
description: |
Same as `/login/sso` but flags the request as an e-sign step-up.
Forces re-authentication regardless of existing session.
operationId: esignSso
parameters:
- $ref: '#/components/parameters/TenantCode'
responses:
'302':
description: Redirect to the IdP AuthnRequest URL.
headers:
Location:
schema: { type: string, format: uri }
/login/callback:
post:
tags: [SSO]
summary: SAML Assertion Consumer Service (SSO callback).
description: |
Receives the SAMLResponse from the IdP, validates it, establishes the
session, and writes audit logs. Body is x-www-form-urlencoded as per
SAML HTTP-POST binding.
operationId: ssoCallback
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
required: [SAMLResponse]
properties:
SAMLResponse:
type: string
description: Base64-encoded SAMLResponse XML.
RelayState:
type: string
description: Opaque IdP relay state echoed back.
responses:
'302':
description: Redirect to the post-login destination on success.
headers:
Location:
schema: { type: string, format: uri }
/logout/slo:
get:
tags: [SSO]
summary: Begin SAML Single Logout.
description: |
Writes a logout audit entry, asks the SAML strategy for the IdP
logout URL, destroys the local session, clears the sessionId cookie,
and redirects to the IdP.
operationId: ssoLogout
responses:
'302':
description: Redirect to the IdP logout URL.
headers:
Location:
schema: { type: string, format: uri }
'500':
description: SAML logout failed (handler returned an error).
/logout/callback:
post:
tags: [SSO]
summary: SAML SLO assertion consumer (POST binding).
operationId: sloCallbackPost
responses:
'302':
description: Redirect to IdP entryPoint or `/`.
get:
tags: [SSO]
summary: SLO callback for IdPs using HTTP-Redirect binding (e.g. Azure).
operationId: sloCallbackGet
responses:
'302':
description: Redirect to IdP entryPoint or `/`.
/azureb2c/callback:
get:
tags: [SSO]
summary: Azure B2C OIDC callback.
description: |
Returns a small HTML page that completes the Azure B2C flow client
side (token handling happens in the page).
operationId: azureB2cCallback
responses:
'200':
description: HTML callback shim.
content:
text/html:
schema:
type: string
/okta/hooks:
get:
tags: [SSO Hooks]
summary: Okta inline-hook verification challenge.
description: |
Echoes the value of the `x-okta-verification-challenge` header back
in JSON, satisfying Okta's one-time hook verification handshake.
operationId: oktaHookVerify
parameters:
- in: header
name: x-okta-verification-challenge
required: true
schema: { type: string }
responses:
'200':
description: Verification response.
content:
application/json:
schema:
type: object
properties:
verification: { type: string }
post:
tags: [SSO Hooks]
summary: Receive an Okta inline-hook event.
operationId: oktaHookEvent
requestBody:
required: true
content:
application/json:
schema:
type: object
description: Okta inline hook payload (see Okta docs).
additionalProperties: true
responses:
'200':
description: Hook acknowledged.
content:
application/json:
schema:
type: object
properties:
message: { type: string, const: 'Hook received' }
components:
parameters:
McpSessionId:
in: header
name: mcp-session-id
required: false
description: Existing MCP session identifier. Omit on the very first call.
schema: { type: string, format: uuid }
McpSessionIdRequired:
in: header
name: mcp-session-id
required: true
schema: { type: string, format: uuid }
TenantCode:
in: query
name: tenantCode
required: true
description: Short code identifying the tenant whose SSO config to use.
schema: { type: string }
EmailHint:
in: query
name: email
required: false
description: |
Optional user email hint. If different from the current session user,
the SAML strategy will force re-authentication.
schema: { type: string, format: email }
schemas:
JsonRpcRequest:
type: object
required: [jsonrpc, method]
properties:
jsonrpc: { type: string, const: '2.0' }
id:
oneOf:
- { type: string }
- { type: integer }
method: { type: string }
params: { type: object, additionalProperties: true }
JsonRpcResponse:
type: object
required: [jsonrpc]
properties:
jsonrpc: { type: string, const: '2.0' }
id:
oneOf:
- { type: string }
- { type: integer }
- { type: 'null' }
result: {}
error:
type: object
properties:
code: { type: integer }
message: { type: string }
data: {}
ErrorEnvelope:
type: object
properties:
error: { type: string }
responses:
InternalError:
description: Unexpected server error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
