API Reference
Complete reference for the SupportOS REST API. Base URL: https://api.supportos.io
Authentication
All API requests must be authenticated. There are two authentication methods: **JWT Bearer Tokens** — Used by the dashboard and programmatic clients. Obtain a token via the /auth/token endpoint. Include it in the Authorization header: `Authorization: Bearer <token>`. Tokens are tenant-scoped, RS256-signed, and expire after 1 hour. **API Keys** — Used for webhook ingestion and server-to-server calls. API keys are created in Settings > API Keys and are scoped to a single tenant. Include the key in the `X-API-Key` header. API keys do not expire but can be revoked at any time. All requests must include a `Content-Type: application/json` header. Rate limits apply: 100 requests/minute for standard endpoints, 500/minute for webhook ingestion.
Webhooks
Ingest events from external platforms. All webhook payloads must be signed with HMAC-SHA256. Compute the signature over the raw request body using your webhook secret and include it in the `X-Signature-256` header. Events are processed idempotently based on `event_id`.
/api/v1/webhooks/eventsX-API-Key + X-Signature-256 (HMAC-SHA256)Receive an event from an external platform. Supported event types: user_reported, message_flagged, csam_hash_match, account_suspended, content_removed, user_blocked, appeal_submitted. Each event is deduplicated by event_id.
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| event_id | string (UUID) | required | Unique identifier for this event — used for idempotency. |
| event_type | string | required | One of: user_reported, message_flagged, csam_hash_match, account_suspended, content_removed, user_blocked, appeal_submitted. |
| timestamp | string (ISO 8601) | required | When the event occurred on the source platform. |
| source | string | required | Identifier for the source platform (e.g. 'dating-frame'). |
| payload | object | required | Event-specific data. Schema varies by event_type. |
| payload.reporter_id | string | optional | ID of the reporting user (user_reported events). |
| payload.reported_user_id | string | optional | ID of the reported user. |
| payload.reason | string | optional | Reason for the report. |
| payload.content | object | optional | Content associated with the event (messages, images, etc.). |
| payload.hash_value | string | optional | Hash value for csam_hash_match events. |
| payload.hash_algorithm | string | optional | Hash algorithm used (e.g. 'photodna', 'md5'). |
Example Request
curl -X POST https://api.supportos.io/api/v1/webhooks/events \
-H "Content-Type: application/json" \
-H "X-API-Key: sk_live_abc123def456" \
-H "X-Signature-256: sha256=a1b2c3d4e5f6..." \
-d '{
"event_id": "evt_9f8e7d6c-5b4a-3c2d-1e0f-a1b2c3d4e5f6",
"event_type": "user_reported",
"timestamp": "2026-04-02T14:30:00.000Z",
"source": "dating-frame",
"payload": {
"reporter_id": "usr_a1b2c3d4",
"reported_user_id": "usr_e5f6g7h8",
"reason": "inappropriate_content",
"content": {
"type": "message",
"text": "Reported message content here",
"message_id": "msg_x1y2z3"
}
}
}'Example Response
{
"id": "tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d",
"event_id": "evt_9f8e7d6c-5b4a-3c2d-1e0f-a1b2c3d4e5f6",
"status": "received",
"created_at": "2026-04-02T14:30:01.123Z"
}Error Responses
| Status | Description |
|---|---|
| 400 | Invalid payload — missing required fields or unknown event_type. |
| 401 | Missing or invalid API key. |
| 403 | HMAC signature verification failed. |
| 409 | Event with this event_id has already been processed (idempotent — safe to retry). |
| 429 | Rate limit exceeded. Retry after the duration in the Retry-After header. |
Tickets
Manage support tickets created from webhooks, user reports, or manual entry. Tickets are classified by AI and can have AI-generated draft responses.
/api/v1/ticketsBearer JWTList tickets for the current tenant. Results are cursor-paginated and sorted by creation date descending.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| status | string | optional | Filter by status: open, in_progress, waiting, resolved, closed. |
| priority | string | optional | Filter by priority: low, medium, high, critical. |
| category | string | optional | Filter by AI-assigned category. |
| cursor | string | optional | Cursor for pagination. Omit for the first page. |
| limit | number | optional | Number of results per page (1–100, default 25). |
Example Request
curl https://api.supportos.io/api/v1/tickets?status=open&priority=high&limit=10 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"data": [
{
"id": "tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d",
"tenant_id": "ten_f1e2d3c4-b5a6-9788-7c6d-5e4f3a2b1c0d",
"status": "open",
"priority": "high",
"category": "harassment",
"subject": "User report: inappropriate messages",
"source": "webhook",
"ai_confidence": 0.92,
"assigned_to": null,
"created_at": "2026-04-02T14:30:01.123Z",
"updated_at": "2026-04-02T14:30:01.123Z"
}
],
"pagination": {
"cursor": "eyJpZCI6InRrdF8zYTJiMWMwZCJ9",
"has_more": true,
"total": 47
}
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Invalid query parameters. |
| 429 | Rate limit exceeded. |
/api/v1/tickets/:idBearer JWTGet full details for a single ticket including AI classification, timeline events, and linked safety cases.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Ticket ID. |
Example Request
curl https://api.supportos.io/api/v1/tickets/tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"id": "tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d",
"tenant_id": "ten_f1e2d3c4-b5a6-9788-7c6d-5e4f3a2b1c0d",
"status": "open",
"priority": "high",
"category": "harassment",
"subject": "User report: inappropriate messages",
"source": "webhook",
"event_id": "evt_9f8e7d6c-5b4a-3c2d-1e0f-a1b2c3d4e5f6",
"ai_classification": {
"category": "harassment",
"confidence": 0.92,
"model": "claude-sonnet-4-20250514",
"provider": "anthropic",
"risk_indicators": ["threatening_language", "repeated_contact"]
},
"assigned_to": null,
"safety_case_id": null,
"timeline": [
{
"id": "evt_c1d2e3f4-a5b6-7c8d-9e0f-a1b2c3d4e5f6",
"type": "ticket_created",
"actor": "system",
"timestamp": "2026-04-02T14:30:01.123Z",
"details": { "source": "webhook" }
},
{
"id": "evt_d2e3f4a5-b6c7-8d9e-0f1a-b2c3d4e5f6a7",
"type": "ai_classified",
"actor": "system",
"timestamp": "2026-04-02T14:30:02.456Z",
"details": { "category": "harassment", "confidence": 0.92 }
}
],
"created_at": "2026-04-02T14:30:01.123Z",
"updated_at": "2026-04-02T14:30:02.456Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Ticket not found or not accessible by this tenant. |
/api/v1/tickets/:id/draftsBearer JWTGenerate an AI draft response for a ticket. The draft uses tenant-configured prompts and relevant knowledge base articles.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Ticket ID. |
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| tone | string | optional | Tone override: professional, empathetic, firm. Defaults to tenant config. |
| instructions | string | optional | Additional instructions for the AI when generating the draft. |
Example Request
curl -X POST https://api.supportos.io/api/v1/tickets/tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d/drafts \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"tone": "empathetic",
"instructions": "Reference our community guidelines"
}'Example Response
{
"id": "drf_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"ticket_id": "tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d",
"content": "Hi there,\n\nThank you for reaching out to us about this. We take reports of harassment very seriously and I want you to know we are looking into this.\n\nOur Community Guidelines clearly state that threatening or intimidating behaviour is not tolerated. We have flagged the reported user for review by our safety team.\n\nWe will update you once our investigation is complete. In the meantime, you can block this user from your settings.\n\nBest regards,\nDating Frame Support",
"confidence": 0.88,
"model": "claude-sonnet-4-20250514",
"provider": "anthropic",
"tokens_used": 342,
"knowledge_articles_used": [
{ "id": "ka_b1c2d3e4", "title": "Community Guidelines — Harassment Policy" }
],
"status": "pending_approval",
"created_at": "2026-04-02T14:35:12.789Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Ticket not found. |
| 422 | Ticket is closed or already has a pending draft. |
| 429 | Rate limit exceeded. |
/api/v1/tickets/:id/drafts/:draftId/approveBearer JWTApprove an AI-generated draft response. The response is sent to the user and the ticket status is updated.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Ticket ID. |
| draftId | string (UUID) | required | Draft ID. |
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| edits | string | optional | Edited content to use instead of the original draft. If omitted, the original draft is sent as-is. |
Example Request
curl -X POST https://api.supportos.io/api/v1/tickets/tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d/drafts/drf_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6/approve \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{}'Example Response
{
"id": "drf_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"status": "approved",
"approved_by": "usr_c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f",
"approved_at": "2026-04-02T14:40:05.321Z",
"ticket_status": "resolved"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Ticket or draft not found. |
| 409 | Draft has already been approved or rejected. |
Safety Cases
Safety cases track safety investigations including CSEA, harassment, threats, and other priority offences. Cases follow a strict status workflow and may trigger mandatory NCA referrals.
/api/v1/casesBearer JWTList safety cases for the current tenant. Supports filtering by status and case type.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| status | string | optional | Filter by status: open, investigating, escalated, referred, closed. |
| caseType | string | optional | Filter by type: csea, harassment, threats, fraud, self_harm, other. |
| cursor | string | optional | Cursor for pagination. |
| limit | number | optional | Results per page (1–100, default 25). |
Example Request
curl https://api.supportos.io/api/v1/cases?status=open&caseType=csea&limit=10 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"data": [
{
"id": "cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6",
"tenant_id": "ten_f1e2d3c4-b5a6-9788-7c6d-5e4f3a2b1c0d",
"case_type": "csea",
"status": "open",
"priority": "critical",
"subject": "Potential CSEA — hash match detected",
"ticket_ids": ["tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d"],
"assigned_to": "usr_c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f",
"sla_deadline": "2026-04-02T15:30:00.000Z",
"evidence_count": 3,
"referral_id": null,
"created_at": "2026-04-02T14:30:05.000Z",
"updated_at": "2026-04-02T14:30:05.000Z"
}
],
"pagination": {
"cursor": "eyJpZCI6ImNhc19lMWYyYTNiNCJ9",
"has_more": false,
"total": 1
}
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Invalid query parameters. |
| 429 | Rate limit exceeded. |
/api/v1/cases/:idBearer JWTGet full details for a safety case including evidence, timeline, and referral status.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Safety case ID. |
Example Request
curl https://api.supportos.io/api/v1/cases/cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"id": "cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6",
"tenant_id": "ten_f1e2d3c4-b5a6-9788-7c6d-5e4f3a2b1c0d",
"case_type": "csea",
"status": "investigating",
"priority": "critical",
"subject": "Potential CSEA — hash match detected",
"description": "PhotoDNA hash match on uploaded image. Automatic evidence preservation triggered.",
"ticket_ids": ["tkt_3a2b1c0d-9e8f-7a6b-5c4d-3e2f1a0b9c8d"],
"assigned_to": "usr_c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f",
"sla_deadline": "2026-04-02T15:30:00.000Z",
"evidence": [
{
"id": "evi_f1a2b3c4-d5e6-7f8a-9b0c-d1e2f3a4b5c6",
"type": "image_hash",
"preserved_at": "2026-04-02T14:30:03.000Z",
"s3_object_lock": true
}
],
"referral": null,
"timeline": [
{
"type": "case_created",
"actor": "system",
"timestamp": "2026-04-02T14:30:05.000Z"
},
{
"type": "evidence_preserved",
"actor": "system",
"timestamp": "2026-04-02T14:30:06.000Z"
}
],
"created_at": "2026-04-02T14:30:05.000Z",
"updated_at": "2026-04-02T14:32:10.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Case not found or not accessible by this tenant. |
/api/v1/cases/:id/statusBearer JWTTransition a safety case to a new status. Status transitions are validated — for example, CSEA cases cannot be closed without a referral.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Safety case ID. |
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| status | string | required | New status: investigating, escalated, referred, closed. |
| reason | string | required | Reason for the status change (logged to audit trail). |
Example Request
curl -X PATCH https://api.supportos.io/api/v1/cases/cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6/status \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"status": "escalated",
"reason": "Confirmed CSEA material — escalating to safeguarding lead"
}'Example Response
{
"id": "cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6",
"status": "escalated",
"previous_status": "investigating",
"updated_at": "2026-04-02T14:45:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Case not found. |
| 422 | Invalid status transition (e.g. closing a CSEA case without referral). |
Evidence
Evidence is immutable content preserved in S3 with Object Lock (Compliance Mode). Evidence cannot be modified or deleted. Every access is logged to the chain-of-custody audit trail.
/api/v1/evidenceBearer JWTList evidence items. Must filter by case_id. Every call to this endpoint is logged to the evidence access audit trail.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| case_id | string (UUID) | required | Safety case ID to list evidence for. |
| cursor | string | optional | Cursor for pagination. |
| limit | number | optional | Results per page (1–100, default 25). |
Example Request
curl https://api.supportos.io/api/v1/evidence?case_id=cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"data": [
{
"id": "evi_f1a2b3c4-d5e6-7f8a-9b0c-d1e2f3a4b5c6",
"case_id": "cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6",
"type": "image_hash",
"description": "PhotoDNA hash match — original image preserved",
"content_type": "image/jpeg",
"size_bytes": 245760,
"hash_sha256": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"s3_key": "evidence/ten_f1e2d3c4/cas_e1f2a3b4/evi_f1a2b3c4.enc",
"object_lock_mode": "COMPLIANCE",
"object_lock_retain_until": "2033-04-02T14:30:03.000Z",
"preserved_at": "2026-04-02T14:30:03.000Z",
"preserved_by": "system",
"created_at": "2026-04-02T14:30:03.000Z"
}
],
"pagination": {
"cursor": null,
"has_more": false,
"total": 1
}
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Missing required case_id parameter. |
| 404 | Case not found or not accessible by this tenant. |
Referrals
NCA (National Crime Agency) referrals for CSEA and other priority offences. Referrals are generated from safety cases and follow a strict workflow. Once submitted, referrals cannot be modified.
/api/v1/referralsBearer JWTList referrals for the current tenant.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| status | string | optional | Filter by status: draft, pending_review, submitted, acknowledged. |
| cursor | string | optional | Cursor for pagination. |
| limit | number | optional | Results per page (1–100, default 25). |
Example Request
curl https://api.supportos.io/api/v1/referrals?status=submitted&limit=10 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"data": [
{
"id": "ref_b1c2d3e4-f5a6-7b8c-9d0e-f1a2b3c4d5e6",
"case_id": "cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6",
"type": "nca",
"status": "submitted",
"submitted_at": "2026-04-02T15:00:00.000Z",
"submitted_by": "usr_c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f",
"reference_number": "NCA-2026-04-0042",
"evidence_count": 3,
"created_at": "2026-04-02T14:50:00.000Z"
}
],
"pagination": {
"cursor": null,
"has_more": false,
"total": 1
}
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 429 | Rate limit exceeded. |
/api/v1/cases/:caseId/referralsBearer JWTCreate a referral from a safety case. For CSEA cases, the system auto-attaches all preserved evidence. The referral enters draft status and must be reviewed before submission.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| caseId | string (UUID) | required | Safety case ID. |
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | required | Referral type: nca, police, other. |
| urgency | string | required | Urgency level: routine, urgent, emergency. |
| summary | string | required | Human-written summary of the referral. |
| contact_details | object | optional | Override contact details for the referral recipient. |
Example Request
curl -X POST https://api.supportos.io/api/v1/cases/cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6/referrals \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"type": "nca",
"urgency": "urgent",
"summary": "CSEA material detected via PhotoDNA hash match. User account suspended. Evidence preserved with full chain of custody."
}'Example Response
{
"id": "ref_b1c2d3e4-f5a6-7b8c-9d0e-f1a2b3c4d5e6",
"case_id": "cas_e1f2a3b4-c5d6-7e8f-9a0b-c1d2e3f4a5b6",
"type": "nca",
"status": "draft",
"urgency": "urgent",
"summary": "CSEA material detected via PhotoDNA hash match. User account suspended. Evidence preserved with full chain of custody.",
"evidence_count": 3,
"created_at": "2026-04-02T14:50:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Case not found. |
| 409 | Case already has an active referral. |
| 422 | Case does not have sufficient evidence for a referral. |
Compliance
Compliance endpoints provide an overview of your regulatory status and generate Ofcom transparency reports as required by the UK Online Safety Act.
/api/v1/compliance/summaryBearer JWTGet a summary of compliance status including SLA adherence, open cases, pending referrals, and upcoming deadlines.
Example Request
curl https://api.supportos.io/api/v1/compliance/summary \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"tenant_id": "ten_f1e2d3c4-b5a6-9788-7c6d-5e4f3a2b1c0d",
"period": {
"from": "2026-03-01T00:00:00.000Z",
"to": "2026-04-02T23:59:59.999Z"
},
"sla_adherence": {
"overall": 0.94,
"csea_response": 1.0,
"priority_offence": 0.97,
"standard_ticket": 0.91
},
"open_cases": {
"total": 4,
"csea": 1,
"priority_offence": 2,
"other": 1
},
"pending_referrals": 1,
"overdue_items": [
{
"type": "ticket",
"id": "tkt_7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"sla_deadline": "2026-04-02T12:00:00.000Z",
"overdue_by_minutes": 150
}
],
"next_transparency_report_due": "2026-06-30T23:59:59.999Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
/api/v1/compliance/transparency-reportBearer JWTGenerate an Ofcom transparency report for the specified period. Returns structured report data.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| from | string (ISO 8601) | required | Start of reporting period. |
| to | string (ISO 8601) | required | End of reporting period. |
Example Request
curl "https://api.supportos.io/api/v1/compliance/transparency-report?from=2026-01-01T00:00:00Z&to=2026-03-31T23:59:59Z" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"report_id": "rpt_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"tenant_id": "ten_f1e2d3c4-b5a6-9788-7c6d-5e4f3a2b1c0d",
"period": {
"from": "2026-01-01T00:00:00.000Z",
"to": "2026-03-31T23:59:59.000Z"
},
"summary": {
"total_reports_received": 1247,
"total_actions_taken": 892,
"total_cases_opened": 156,
"total_referrals_made": 3,
"average_response_time_hours": 2.4,
"sla_adherence_rate": 0.94
},
"categories": {
"csea": { "reports": 8, "cases": 5, "referrals": 3, "actions": 8 },
"harassment": { "reports": 412, "cases": 67, "referrals": 0, "actions": 298 },
"threats": { "reports": 89, "cases": 23, "referrals": 0, "actions": 64 },
"fraud": { "reports": 201, "cases": 34, "referrals": 0, "actions": 178 },
"self_harm": { "reports": 45, "cases": 12, "referrals": 0, "actions": 39 },
"other": { "reports": 492, "cases": 15, "referrals": 0, "actions": 305 }
},
"generated_at": "2026-04-02T15:00:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Invalid or missing date range parameters. |
/api/v1/compliance/transparency-report/exportBearer JWTExport a transparency report as JSON or CSV. Returns a download URL.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| from | string (ISO 8601) | required | Start of reporting period. |
| to | string (ISO 8601) | required | End of reporting period. |
| format | string | required | Export format: json or csv. |
Example Request
curl "https://api.supportos.io/api/v1/compliance/transparency-report/export?from=2026-01-01T00:00:00Z&to=2026-03-31T23:59:59Z&format=csv" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"download_url": "https://supportos-exports.s3.eu-west-2.amazonaws.com/exports/ten_f1e2d3c4/rpt_a1b2c3d4.csv?X-Amz-Expires=3600&...",
"format": "csv",
"expires_at": "2026-04-02T16:00:00.000Z",
"size_bytes": 15420
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Invalid date range or unsupported format. |
Workflows
Configure automated workflows that trigger on specific conditions (e.g. ticket created with category X, safety case escalated). Workflows consist of trigger conditions and ordered steps.
/api/v1/workflowsBearer JWTList all workflows for the current tenant.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| active | boolean | optional | Filter by active/inactive status. |
| cursor | string | optional | Cursor for pagination. |
| limit | number | optional | Results per page (1–100, default 25). |
Example Request
curl https://api.supportos.io/api/v1/workflows?active=true \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"data": [
{
"id": "wfl_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"name": "Auto-escalate CSEA tickets",
"description": "Automatically creates safety case and escalates when CSEA is detected",
"active": true,
"trigger": {
"event": "ticket.classified",
"conditions": { "category": "csea" }
},
"steps": [
{ "order": 1, "action": "create_safety_case", "config": { "case_type": "csea", "priority": "critical" } },
{ "order": 2, "action": "preserve_evidence", "config": {} },
{ "order": 3, "action": "assign_to_role", "config": { "role": "safeguarding_lead" } },
{ "order": 4, "action": "send_notification", "config": { "channel": "urgent", "template": "csea_alert" } }
],
"executions_count": 5,
"last_executed_at": "2026-04-01T09:15:00.000Z",
"created_at": "2026-03-01T10:00:00.000Z",
"updated_at": "2026-03-15T14:20:00.000Z"
}
],
"pagination": {
"cursor": null,
"has_more": false,
"total": 1
}
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
/api/v1/workflowsBearer JWTCreate a new workflow. CSEA mandatory workflows cannot be created or modified by tenants.
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Workflow name. |
| description | string | optional | Workflow description. |
| trigger | object | required | Trigger configuration: { event: string, conditions: object }. |
| steps | array | required | Ordered array of steps: [{ order: number, action: string, config: object }]. |
| active | boolean | optional | Whether to activate immediately (default: false). |
Example Request
curl -X POST https://api.supportos.io/api/v1/workflows \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "High-priority ticket assignment",
"description": "Auto-assign high priority tickets to senior agents",
"trigger": {
"event": "ticket.classified",
"conditions": { "priority": "high" }
},
"steps": [
{ "order": 1, "action": "assign_to_role", "config": { "role": "senior_agent" } },
{ "order": 2, "action": "send_notification", "config": { "channel": "slack", "template": "high_priority_ticket" } }
],
"active": true
}'Example Response
{
"id": "wfl_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
"name": "High-priority ticket assignment",
"active": true,
"trigger": {
"event": "ticket.classified",
"conditions": { "priority": "high" }
},
"steps": [
{ "order": 1, "action": "assign_to_role", "config": { "role": "senior_agent" } },
{ "order": 2, "action": "send_notification", "config": { "channel": "slack", "template": "high_priority_ticket" } }
],
"created_at": "2026-04-02T15:10:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Invalid workflow definition — missing trigger or steps. |
| 422 | Workflow conflicts with a mandatory system workflow. |
/api/v1/workflows/:idBearer JWTUpdate an existing workflow. Only non-mandatory workflows can be modified.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Workflow ID. |
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | optional | Updated name. |
| description | string | optional | Updated description. |
| trigger | object | optional | Updated trigger configuration. |
| steps | array | optional | Updated steps array. |
| active | boolean | optional | Enable or disable the workflow. |
Example Request
curl -X PATCH https://api.supportos.io/api/v1/workflows/wfl_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"active": false
}'Example Response
{
"id": "wfl_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
"name": "High-priority ticket assignment",
"active": false,
"updated_at": "2026-04-02T15:15:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Workflow not found. |
| 403 | Cannot modify a mandatory system workflow. |
/api/v1/workflows/:idBearer JWTSoft-delete a workflow. Mandatory system workflows cannot be deleted.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Workflow ID. |
Example Request
curl -X DELETE https://api.supportos.io/api/v1/workflows/wfl_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"id": "wfl_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
"deleted": true,
"deleted_at": "2026-04-02T15:20:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Workflow not found. |
| 403 | Cannot delete a mandatory system workflow. |
Connectors
Connectors integrate external platforms (email providers, chat systems, CRMs) with SupportOS. Each connector has inbound mappings (how external data maps to SupportOS entities) and outbound actions (what actions SupportOS can push back to the external platform).
/api/v1/connectorsBearer JWTList all connectors for the current tenant.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| status | string | optional | Filter by status: active, inactive, error. |
| cursor | string | optional | Cursor for pagination. |
| limit | number | optional | Results per page (1–100, default 25). |
Example Request
curl https://api.supportos.io/api/v1/connectors \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"data": [
{
"id": "con_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"name": "Dating Frame Production",
"type": "webhook",
"status": "active",
"config": {
"webhook_url": "https://api.supportos.io/api/v1/webhooks/events",
"signing_secret_last4": "f6a7"
},
"inbound_mappings_count": 3,
"outbound_actions_count": 2,
"last_event_at": "2026-04-02T14:30:01.000Z",
"created_at": "2026-03-01T10:00:00.000Z"
}
],
"pagination": {
"cursor": null,
"has_more": false,
"total": 1
}
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
/api/v1/connectorsBearer JWTCreate a new connector. A webhook signing secret is generated and returned once — store it securely.
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Display name for the connector. |
| type | string | required | Connector type: webhook, email, api. |
| config | object | optional | Type-specific configuration (e.g. SMTP settings for email). |
Example Request
curl -X POST https://api.supportos.io/api/v1/connectors \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "Dating Frame Staging",
"type": "webhook"
}'Example Response
{
"id": "con_e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b",
"name": "Dating Frame Staging",
"type": "webhook",
"status": "active",
"config": {
"webhook_url": "https://api.supportos.io/api/v1/webhooks/events",
"signing_secret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
},
"created_at": "2026-04-02T15:25:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Invalid connector configuration. |
/api/v1/connectors/:id/mappingsBearer JWTCreate an inbound field mapping for a connector. Maps external event fields to SupportOS ticket fields.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Connector ID. |
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| event_type | string | required | External event type this mapping applies to. |
| field_mappings | array | required | Array of { source: string, target: string, transform?: string } mappings. |
Example Request
curl -X POST https://api.supportos.io/api/v1/connectors/con_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6/mappings \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"event_type": "user_reported",
"field_mappings": [
{ "source": "payload.reporter_id", "target": "reporter_external_id" },
{ "source": "payload.reported_user_id", "target": "subject_external_id" },
{ "source": "payload.reason", "target": "category", "transform": "map_category" }
]
}'Example Response
{
"id": "map_c1d2e3f4-a5b6-7c8d-9e0f-a1b2c3d4e5f6",
"connector_id": "con_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"event_type": "user_reported",
"field_mappings": [
{ "source": "payload.reporter_id", "target": "reporter_external_id" },
{ "source": "payload.reported_user_id", "target": "subject_external_id" },
{ "source": "payload.reason", "target": "category", "transform": "map_category" }
],
"created_at": "2026-04-02T15:30:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Connector not found. |
| 400 | Invalid field mapping — unknown target field or transform. |
/api/v1/connectors/:id/actionsBearer JWTCreate an outbound action for a connector. Defines what actions SupportOS can push to the external platform.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Connector ID. |
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| action_type | string | required | Action type: suspend_user, remove_content, send_warning, restore_content. |
| endpoint | string | required | URL to call when this action is triggered. |
| method | string | required | HTTP method: POST, PUT, PATCH, DELETE. |
| headers | object | optional | Additional headers to include in the request. |
| payload_template | string | required | JSON template with {{variable}} placeholders for the request body. |
Example Request
curl -X POST https://api.supportos.io/api/v1/connectors/con_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6/actions \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"action_type": "suspend_user",
"endpoint": "https://api.datingframe.com/v2/users/{{user_id}}/suspend",
"method": "POST",
"headers": { "X-Service-Key": "{{service_key}}" },
"payload_template": "{ \"reason\": \"{{reason}}\", \"duration\": \"{{duration}}\" }"
}'Example Response
{
"id": "act_d1e2f3a4-b5c6-7d8e-9f0a-b1c2d3e4f5a6",
"connector_id": "con_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"action_type": "suspend_user",
"endpoint": "https://api.datingframe.com/v2/users/{{user_id}}/suspend",
"method": "POST",
"created_at": "2026-04-02T15:35:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Connector not found. |
| 400 | Invalid action configuration — missing endpoint or payload_template. |
Knowledge Base
Manage knowledge base articles used by AI to generate accurate draft responses. Articles are embedded as vectors using pgvector for semantic search. Up to 5 relevant articles are injected into AI context per query.
/api/v1/knowledgeBearer JWTList knowledge base articles for the current tenant.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| category | string | optional | Filter by category. |
| status | string | optional | Filter by status: published, draft, archived. |
| cursor | string | optional | Cursor for pagination. |
| limit | number | optional | Results per page (1–100, default 25). |
Example Request
curl https://api.supportos.io/api/v1/knowledge?status=published&limit=10 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"data": [
{
"id": "ka_b1c2d3e4-f5a6-7b8c-9d0e-f1a2b3c4d5e6",
"title": "Community Guidelines — Harassment Policy",
"category": "policies",
"status": "published",
"content_preview": "Our platform has a zero-tolerance policy for harassment...",
"word_count": 1240,
"embedding_status": "indexed",
"last_used_at": "2026-04-02T14:35:12.000Z",
"created_at": "2026-02-15T10:00:00.000Z",
"updated_at": "2026-03-20T14:30:00.000Z"
}
],
"pagination": {
"cursor": null,
"has_more": false,
"total": 1
}
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
/api/v1/knowledgeBearer JWTCreate a new knowledge base article. The article is automatically embedded for semantic search after creation.
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| title | string | required | Article title. |
| content | string | required | Article content in plain text or Markdown. |
| category | string | required | Article category (e.g. policies, procedures, faq). |
| tags | string[] | optional | Tags for filtering and organisation. |
| status | string | optional | Initial status: draft or published (default: draft). |
Example Request
curl -X POST https://api.supportos.io/api/v1/knowledge \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"title": "Account Deletion Process",
"content": "When a user requests account deletion, the following steps must be followed:\n\n1. Verify the user identity via email confirmation.\n2. Initiate a 30-day cooling-off period.\n3. After 30 days, permanently delete all personal data.\n4. Retain anonymised usage data for compliance purposes.",
"category": "procedures",
"tags": ["gdpr", "account", "deletion"],
"status": "published"
}'Example Response
{
"id": "ka_e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b",
"title": "Account Deletion Process",
"category": "procedures",
"status": "published",
"tags": ["gdpr", "account", "deletion"],
"word_count": 52,
"embedding_status": "pending",
"created_at": "2026-04-02T15:40:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Missing required fields (title, content, or category). |
/api/v1/knowledge/searchBearer JWTSemantic search across knowledge base articles using pgvector. Returns the top matching articles ranked by relevance.
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| query | string | required | Natural language search query. |
| limit | number | optional | Max results to return (1–10, default 5). |
| category | string | optional | Restrict search to a specific category. |
| threshold | number | optional | Minimum similarity score (0–1, default 0.5). |
Example Request
curl -X POST https://api.supportos.io/api/v1/knowledge/search \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"query": "What is our harassment policy?",
"limit": 3
}'Example Response
{
"results": [
{
"id": "ka_b1c2d3e4-f5a6-7b8c-9d0e-f1a2b3c4d5e6",
"title": "Community Guidelines — Harassment Policy",
"category": "policies",
"content_preview": "Our platform has a zero-tolerance policy for harassment...",
"similarity": 0.94,
"word_count": 1240
},
{
"id": "ka_c2d3e4f5-a6b7-8c9d-0e1f-a2b3c4d5e6f7",
"title": "Escalation Procedures for Repeat Offenders",
"category": "procedures",
"content_preview": "When a user has multiple harassment reports...",
"similarity": 0.78,
"word_count": 890
}
],
"query_embedding_tokens": 12
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 400 | Missing search query. |
Patterns
AI-detected patterns across tickets and safety cases. Patterns surface recurring issues, emerging threats, and anomalies that may require attention. Patterns can be confirmed or dismissed by operators.
/api/v1/patternsBearer JWTList detected patterns for the current tenant.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| status | string | optional | Filter by status: detected, confirmed, dismissed. |
| severity | string | optional | Filter by severity: low, medium, high, critical. |
| cursor | string | optional | Cursor for pagination. |
| limit | number | optional | Results per page (1–100, default 25). |
Example Request
curl https://api.supportos.io/api/v1/patterns?status=detected&severity=high \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Example Response
{
"data": [
{
"id": "pat_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"title": "Surge in harassment reports from London region",
"description": "42% increase in harassment reports originating from users in the London area over the past 7 days, compared to the 30-day average.",
"severity": "high",
"status": "detected",
"category": "harassment",
"affected_tickets": 23,
"confidence": 0.87,
"detected_at": "2026-04-02T06:00:00.000Z",
"time_range": {
"from": "2026-03-26T00:00:00.000Z",
"to": "2026-04-02T00:00:00.000Z"
},
"created_at": "2026-04-02T06:00:00.000Z"
}
],
"pagination": {
"cursor": null,
"has_more": false,
"total": 1
}
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
/api/v1/patterns/:id/reviewBearer JWTConfirm or dismiss a detected pattern. Confirmed patterns remain visible and may trigger workflows. Dismissed patterns are hidden from the default view.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | required | Pattern ID. |
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| action | string | required | Review action: confirm or dismiss. |
| notes | string | optional | Optional notes about the review decision. |
Example Request
curl -X PATCH https://api.supportos.io/api/v1/patterns/pat_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6/review \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"action": "confirm",
"notes": "Correlates with a viral social media post targeting our users. Increasing moderation capacity."
}'Example Response
{
"id": "pat_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"status": "confirmed",
"reviewed_by": "usr_c4d5e6f7-a8b9-0c1d-2e3f-4a5b6c7d8e9f",
"reviewed_at": "2026-04-02T15:50:00.000Z",
"notes": "Correlates with a viral social media post targeting our users. Increasing moderation capacity."
}Error Responses
| Status | Description |
|---|---|
| 401 | Missing or invalid JWT. |
| 404 | Pattern not found. |
| 400 | Invalid action — must be 'confirm' or 'dismiss'. |
User Reports
Public-facing endpoint for the user reporting widget. Allows end-users of tenant platforms to submit reports directly. Authenticated via the widget embed token, not a user JWT.
/api/v1/reportsWidget Embed Token (X-Widget-Token header)Submit a user report from the embedded reporting widget. Creates a ticket in the tenant's queue. No user authentication required — the widget embed token identifies the tenant.
Body Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| reporter_id | string | optional | External user ID of the reporter (optional — anonymous reports supported). |
| reported_user_id | string | optional | External user ID of the reported user (if applicable). |
| category | string | required | Report category: harassment, inappropriate_content, spam, scam, underage, csea_concern, self_harm, other. |
| description | string | required | Free-text description of the report. |
| content_ids | string[] | optional | IDs of content items on the tenant platform related to this report. |
| metadata | object | optional | Additional metadata from the tenant platform (e.g. page URL, session info). |
Example Request
curl -X POST https://api.supportos.io/api/v1/reports \
-H "Content-Type: application/json" \
-H "X-Widget-Token: wgt_a1b2c3d4e5f6g7h8i9j0" \
-d '{
"reporter_id": "usr_a1b2c3d4",
"reported_user_id": "usr_e5f6g7h8",
"category": "harassment",
"description": "This user has been sending threatening messages repeatedly after I asked them to stop.",
"content_ids": ["msg_x1y2z3", "msg_a4b5c6"],
"metadata": {
"page_url": "https://datingframe.com/messages/usr_e5f6g7h8",
"platform": "ios_app"
}
}'Example Response
{
"id": "rpt_a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"ticket_id": "tkt_f1e2d3c4-b5a6-7c8d-9e0f-a1b2c3d4e5f6",
"status": "received",
"message": "Thank you for your report. Our team will review it shortly.",
"created_at": "2026-04-02T16:00:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 400 | Missing required fields (category or description). |
| 401 | Missing or invalid widget embed token. |
| 429 | Rate limit exceeded — max 10 reports per minute per IP. |