URL
POST https://<PRIVATE_DEPLOYMENT_URL>/api/v1/conversationAuthentication headers
- Authorization: Bearer YOUR_API_KEY
- X-API-Key: YOUR_API_KEY
- Idempotency-Key: optional-request-key
Conversation API
Conversation API
HTTP API for the private dialogue layer: text, images, voice, per-user memory, a global persona profile per key, and knowledge-driven replies through custom KB.
The Conversation API runs inside a private deployment. You receive a dedicated base URL and use one endpoint for all dialogue scenarios.
URL
POST https://<PRIVATE_DEPLOYMENT_URL>/api/v1/conversationAuthentication headers
Runtime facts
image limit
≈ 5 MB decoded
voice limit
≈ 25 MB decoded
default key limit
60 RPM
default IP limit
360 RPM
user_id is required. At least one of message, image_b64, or voice_b64 must be present. If both message and voice_b64 are sent, text takes priority while voice remains as extra context.
| Field | Type | Required | Description |
|---|---|---|---|
| user_id | string (1..128) | Yes | Stable identifier of the end user in your own system. It is used as the memory key. |
| message | string (1..4000) | No | Text query. Can be used alone or together with an image. |
| image_b64 | base64 string | No | Image without the data: prefix. Supported mimes: image/jpeg, image/jpg, image/png, image/webp. |
| image_mime | string | With image_b64 | Image MIME type. If image_mime is present without image_b64, the request is rejected. |
| voice_b64 | base64 string | No | Voice input. When message is absent, the service attempts to transcribe audio into text. |
| voice_mime | string | Recommended | Supported values: audio/aac, audio/m4a, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/opus, audio/wav, audio/webm, audio/x-wav. |
| persona | object | No | Updates the global persona profile for the API key. Partial fields are merged into the existing profile. |
persona is the shared profile stored at API-key level. It defines the role, style, and positioning, while the engine keeps individual history per user_id on top of that baseline.
| Field | Type | Description |
|---|---|---|
| name | string (1..64) | Persona name. |
| age | integer 1..120 | Stylistic nuance rather than a business rule. |
| gender | male | female | Persona gender. |
| zodiac | 12 fixed values | Aries..Pisces. |
| temperament | object | Weights for sanguine / choleric / phlegmatic / melancholic; normalized inside the engine. |
| sociality | introvert | ambivert | extrovert | Behavioral social vector. |
| archetypes | array up to 16 enum values | Examples: Sage, Explorer, Creator, Caregiver. |
| role | string (1..1000) | Primary working description of role, expertise, constraints, and tone. |
A successful response contains the generated reply, latency_ms for SLA observation, latency_breakdown for deeper tracing, and request_id for incident tracking.
Response example
{
"reply": "Basic is usually the best starting point: it covers standard workloads without extra overhead. If you need priority support and a higher request ceiling, Pro is the better fit.",
"latency_ms": 842,
"latency_breakdown": {
"queue_latency_ms": 44,
"worker_latency_ms": 798,
"total_latency_ms": 842
},
"request_id": "4611686018427387904-7-a1b2c3"
}All errors use the envelope { detail: { code, message, request_id? } }. request_id may be absent for some early 4xx validation failures.
| HTTP | code | Description | Retry |
|---|---|---|---|
| 401 | missing_api_key | No API key provided. | No |
| 401 | invalid_api_key | Key is invalid or deactivated. | No |
| 402 | no_requests | Not enough request balance for API usage. | After refill |
| 400 | invalid_payload | Invalid request shape, missing required field combinations, or broken base64. | After fix |
| 400 | invalid_voice_format / invalid_voice_mime / voice_transcription_failed | Voice payload is unsupported, undetected, or could not be transcribed. | After fix |
| 409 | idempotency_in_flight / idempotency_key_reused_with_different_payload | The idempotency key is already in progress or was reused with a different payload. | Carefully |
| 429 | rate_limited / rate_limited_ip | Per-key or per-IP limit exceeded. Retry-After: 60 is returned. | Yes |
| 503 | queue_unavailable / rate_limiter_unavailable / idempotency_unavailable | Temporary queue, rate-limiter, or idempotency-storage outage. | Yes |
| 504 | upstream_timeout | Worker or model did not respond in time. | Yes |
| 500 | internal_error | Unexpected internal failure. | Yes |
Below are baseline examples for a private deployment. In production you only replace the base URL and the API key.
Request example
{
"user_id": "usr-42",
"message": "Help me choose a starter plan and explain how it differs from Pro.",
"image_b64": null,
"image_mime": null,
"voice_b64": null,
"voice_mime": null,
"persona": {
"name": "Nora",
"gender": "female",
"sociality": "ambivert",
"archetypes": ["Sage", "Explorer"],
"role": "You are the private AI assistant for Acme. You answer product and support questions, rely on the official knowledge base, keep replies concise, and escalate billing disputes to a human."
}
}cURL · bash
curl -X POST "https://<PRIVATE_DEPLOYMENT_URL>/api/v1/conversation" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Idempotency-Key: req-usr-42-001" \
-H "Content-Type: application/json" \
-d '{
"user_id": "usr-42",
"message": "Help me choose a starter plan and explain how it differs from Pro.",
"image_b64": null,
"image_mime": null,
"voice_b64": null,
"voice_mime": null,
"persona": {
"name": "Nora",
"gender": "female",
"sociality": "ambivert",
"archetypes": ["Sage", "Explorer"],
"role": "You are the private AI assistant for Acme. You answer product and support questions, rely on the official knowledge base, keep replies concise, and escalate billing disputes to a human."
}
}'JavaScript / fetch · ts
const API_URL = 'https://<PRIVATE_DEPLOYMENT_URL>';
const API_KEY = 'YOUR_API_KEY';
const body = {
"user_id": "usr-42",
"message": "Help me choose a starter plan and explain how it differs from Pro.",
"image_b64": null,
"image_mime": null,
"voice_b64": null,
"voice_mime": null,
"persona": {
"name": "Nora",
"gender": "female",
"sociality": "ambivert",
"archetypes": ["Sage", "Explorer"],
"role": "You are the private AI assistant for Acme. You answer product and support questions, rely on the official knowledge base, keep replies concise, and escalate billing disputes to a human."
}
};
const response = await fetch(`${API_URL}/api/v1/conversation`, {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': 'req-usr-42-001'
},
body: JSON.stringify(body)
});
console.log(response.status, await response.json());Python / requests · py
import requests
API_URL = 'https://<PRIVATE_DEPLOYMENT_URL>'
API_KEY = 'YOUR_API_KEY'
payload = {
"user_id": "usr-42",
"message": "Help me choose a starter plan and explain how it differs from Pro.",
"image_b64": null,
"image_mime": null,
"voice_b64": null,
"voice_mime": null,
"persona": {
"name": "Nora",
"gender": "female",
"sociality": "ambivert",
"archetypes": ["Sage", "Explorer"],
"role": "You are the private AI assistant for Acme. You answer product and support questions, rely on the official knowledge base, keep replies concise, and escalate billing disputes to a human."
}
}
resp = requests.post(
f"{API_URL}/api/v1/conversation",
headers={
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json',
'Idempotency-Key': 'req-usr-42-001',
},
json=payload,
timeout=30,
)
print(resp.status_code, resp.json())The KB is attached to an API key and is automatically applied to all user_id values under that key. At the moment KB is managed outside the HTTP endpoint: you upload JSON and the index is rebuilt in the background.
KB JSON example
[
{
"id": "faq-billing-1",
"category": "support",
"tags": ["billing", "how do I pay", "refund", "plan"],
"text": "Payment is processed after order confirmation. If the issue is about refunds or disputed charges, collect context first and hand the case to a human."
},
{
"id": "faq-plan-basic",
"category": "sales",
"tags": ["basic", "starter plan", "getting started"],
"text": "Basic is the right entry plan for first rollout and standard workload. Explain the scenario first, then compare Basic and Pro briefly in terms of limits and support."
}
]We can map how Synchatica should be deployed into your contour, which persona and KB fields to define, and where moderation, handoff, and request tracing make sense.