Chat API
Send messages through CID222's safety pipeline to any supported LLM provider. Input and output are filtered for PII, toxicity, and prompt injection in real time, and the response is streamed back as Server-Sent Events.
Create Chat Completion
POST /chat/completions
Streams a model completion through the input and output safety filters. The response is always Server-Sent Events (SSE) — there is no non-streaming JSON body.
Authentication
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Model ID enabled for your tenant (e.g. "gpt-4o", "claude-sonnet-4-6") |
messages | array | Yes | Conversation messages. content is a string or an array of content parts |
provider | string | No | openai, azure_openai, anthropic, google. Inferred from the model when omitted |
stream | boolean | No | Server-Sent Events streaming. Defaults to true for this endpoint |
temperature | number | No | Sampling temperature, 0–2 |
max_tokens | number | No | Maximum tokens in the response |
top_p | number | No | Nucleus sampling, 0–1 |
session_id | string | No | Attach this turn to a conversation session (UUID) |
contexts | string[] | No | RAG passages used for grounding / hallucination checks |
documents | array | No | Documents (pdf/docx/txt/csv, base64) auto-parsed, redacted, and added as context |
content_filter | string | No | Filter nickname overriding the tenant default |
Message Format
// Plain text{ "role": "user", "content": "Message content" }// Multimodal: text + image{"role": "user","content": [{ "type": "text", "text": "What's in this image?" },{ "type": "image_url", "image_url": { "url": "data:image/png;base64,...", "detail": "auto" } }]}// Text + document{"role": "user","content": [{ "type": "text", "text": "Summarize this contract" },{ "type": "document", "document": { "data": "JVBERi0xLjQK...", "type": "pdf", "name": "contract.pdf" } }]}
Images & documents are scanned too
Example Request
curl -N -X POST https://api.cid222.ai/chat/completions \-H "Authorization: Bearer cid_key_your_api_key" \-H "Content-Type: application/json" \-d '{"model": "gpt-4o","messages": [{"role": "system","content": "You are a helpful customer service agent."},{"role": "user","content": "My name is John Smith and my email is john@example.com"}]}'
Streaming Response
The response is a text/event-stream. Each event is a JSON object on a data: line. Model text arrives in a top-level content field; the gateway buffers the LLM output for filtering and sends the complete answer as a single filtered-response event (finish_reason: stop). The stream ends with a token_usage event followed by data: [DONE].
data: {"type":"user_message_processed","content":"My name is [NAME] and my email is [EMAIL]","original_had_issues":true,"entities_count":2,"masked_count":2,"flagged_count":0,"action_taken":"masked","filter_duration_ms":142}data: {"id":"filtered-response","content":"Hello! How can I help you today?","finish_reason":"stop","filtered":false,"entities_masked":0}data: {"type":"token_usage","usage":{"prompt_tokens":320,"completion_tokens":12,"total_tokens":332}}data: [DONE]
Event Types
The stream interleaves model output with safety-pipeline events:
| Event | Description |
|---|---|
Text chunk (no type) | Model text in a top-level content string: {"id":"...","object":"chat.completion.chunk","created":...,"model":"...","content":"Hello","finish_reason":null} |
id: "filtered-response" | The gateway buffers the model output for filtering, then sends the complete filtered answer as one event: content (full text), finish_reason: "stop", filtered, entities_masked. Treat this as the final answer |
user_message_processed | PII or safety match in the prompt was masked or flagged before sending (content is the masked prompt, plus masked_count, flagged_count, action_taken) |
content_rejected | Prompt blocked (e.g. jailbreak). Carries error and entities; not forwarded to the provider |
output_content_rejected | Response blocked (severity: "critical", reason, actions_applied) |
output_content_warning | Response contains flagged content (severity: "warning", message, actions_applied) |
token_usage | Token usage (usage.prompt_tokens, usage.completion_tokens, usage.total_tokens) |
documents_processed | Attached documents[] were parsed and filtered (count, summaries, processing_time_ms) |
hallucination | Background hallucination check flagged the response (RAG contexts flows) |
Blocked Content
If the input or output violates policy, the pipeline emits a content_rejected or output_content_rejected event instead of model text and ends the stream. Blocked input is never sent to the provider, so no tokens are billed.
data: {"error":"Content contains prohibited information","type":"content_rejected","entities":[{"type":"jailbreak","action":"reject","confidence":0.96}]}data: [DONE]
Supported Models
The model parameter accepts any model enabled for your tenant. Call GET /models to list what is available.
| Provider | Models |
|---|---|
| OpenAI | gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-3.5-turbo |
| Anthropic | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 |
gemini-2.5-pro, gemini-2.5-flash | |
| Azure OpenAI | gpt-4o, gpt-4o-mini, gpt-4-turbo (your deployment names) |
Error Codes
| Code | Description |
|---|---|
| 400 | Invalid request body or parameters |
| 401 | Invalid or missing authentication |
| 403 | Forbidden (insufficient role or scope) |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
| 503 | Provider or ML service unavailable |