API Documentation

Complete reference for the comxbot API. All endpoints use JSON request/response bodies, return a consistent error envelope, and support idempotency keys for safe retries.

Base URL

https://app.comxbot.com

All API paths are relative to this base URL. Use HTTPS for all requests.

Authentication

Public endpoints

Routes under /api/public/v1/ do not require authentication. They are rate-limited by IP address. These endpoints power the embeddable chat widget and public forms.

Organisation endpoints

Routes under /api/org/v1/ require a valid Clerk session with an active organisation context. Include the session token via cookie or the Authorization: Bearer <token> header.

API Keys

For server-to-server integration, generate Organisation API Keys in Settings > API Keys. Pass the key as a Bearer token. Keys are scoped to the organisation and can be rotated at any time.

Webhook verification

All inbound webhooks must be verified against the raw request body. Clerk uses Svix signatures, Stripe uses Stripe-Signature. Never transform the body before verification.

Security note: Never expose Organisation API keys in client-side code. Use them only in server-to-server communication.

Public API

No authentication required. Rate-limited by IP address (20 requests/minute for chat, 5/minute for enquiries).

MethodEndpoint
POST/api/public/v1/chat/sessions
POST/api/public/v1/chat/messages
POST/api/public/v1/enquiries
GET/api/public/v1/answers/{answerId}

Organisation API

Requires Clerk session with active organisation context or a valid Organisation API Key.

MethodEndpoint
POST/api/org/v1/sources
POST/api/org/v1/ingest-jobs
GET/api/org/v1/sources/{sourceId}/health
GET/api/org/v1/inbox/threads
POST/api/org/v1/handoffs
POST/api/org/v1/actions/proposals
POST/api/org/v1/actions/{proposalId}/approve
POST/api/org/v1/actions/{proposalId}/execute
GET/api/org/v1/templates
POST/api/org/v1/templates
GET/api/org/v1/safeguarding
PUT/api/org/v1/safeguarding
POST/api/org/v1/thinkguide/sessions
POST/api/org/v1/thinkguide/sessions/{sessionId}/step
GET/api/org/v1/thinkguide/sessions/{sessionId}
GET/api/org/v1/learner-accessibility/{learnerId}
PUT/api/org/v1/learner-accessibility/{learnerId}

Webhooks

Inbound webhooks from third-party services. Always verify signatures before processing.

MethodEndpoint
POST/api/webhooks/clerk
POST/api/webhooks/stripe

Webhook Verification Example

When comxbot sends webhooks to your custom action endpoints, each request includes a signature header:

const crypto = require('crypto');

function verifyComxbotWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your handler:
const signature = req.headers['x-comx-signature'];
const isValid = verifyComxbotWebhook(
  JSON.stringify(req.body),
  signature,
  process.env.COMX_WEBHOOK_SECRET
);

if (!isValid) {
  return res.status(401).json({ error: 'Invalid signature' });
}

The signature is HMAC-SHA256 of the raw request body using your webhook secret (found in Settings > Webhooks). Always verify before processing.

Error Codes

All errors follow a consistent envelope format:

{
  "error": {
    "code": "COMX_VALIDATION_ERROR",
    "message": "Human-readable description",
    "request_id": "req_abc123",
    "retryable": false,
    "details": { "field": "email" }
  }
}
CodeHTTP
COMX_VALIDATION_ERROR400
COMX_UNAUTHENTICATED401
COMX_FORBIDDEN403
COMX_NOT_FOUND404
COMX_IDEMPOTENCY_CONFLICT409
COMX_POLICY_BLOCK403
COMX_RATE_LIMITED429
COMX_PROVIDER_UNAVAILABLE503
COMX_INTERNAL_ERROR500

Rate Limiting

Public chat

20

requests per minute per IP

Public enquiries

5

requests per minute per IP

Org API

60

requests per minute per key

When rate-limited, the response includes a Retry-After header with the number of seconds to wait. All mutating endpoints accept an Idempotency-Key header for safe retries.

// Rate limit response headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 54
X-RateLimit-Reset: 1716550000
Retry-After: 42  // Only present on 429 responses

Need help? Contact support or visit the Help Centre.