Quickstart
Conversational Triage API lets you build a free-text triage experience: the patient describes their problem in their own words, the assistant asks follow-up questions, and the API maintains a structured assessment behind the conversation — evidence, differential conditions, and a triage recommendation.
Unlike Engine API, which is stateless and expects you to send the full evidence list with every request, Conversational Triage API is stateful: the server owns the conversation, so each request carries only the new user message.
Setup
The API is available at:
https://api.infermedica.com/api/ct/v2All HTTP paths on this page are relative to that base URL. The realtime WebSocket transport lives at wss://api.infermedica.com/api/ct/v2/realtime.
Authentication
Every request carries a bearer token in the Authorization header. Tokens are issued and validated by the Infermedica API gateway, and the token must carry the ct:conversations scope.
Authorization: Bearer <token>See Authentication for details.
Choose a transport
The same conversation model is exposed through three interchangeable flavors — pick the one that matches your client:
| Transport | Use when |
|---|---|
Blocking HTTP — POST /turns | Server-to-server integrations, or any client that can wait for the full reply. |
HTTP streaming — POST /turns/stream | Web and mobile clients that want to render text as it is generated. |
WebSocket — /realtime | Voice channels and long-lived sessions with interruption support. |
Building an orchestrator on the A2A protocol (opens in a new tab) instead? See A2A integration — it exposes the same conversation model as a remote A2A agent.
The rest of this page walks through a conversation over blocking HTTP.
1. Create a conversation
Start by creating a conversation. Both settings and assessment are required objects, but every field inside them is optional — send empty objects to accept the defaults configured for your instance.
curl "https://api.infermedica.com/api/ct/v2/conversations" \
-X "POST" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"language": "en",
"channel": "text",
"ui_widgets_enabled": false,
"opening_message_enabled": false
},
"assessment": {
"age": { "value": 35, "unit": "year" },
"sex": "female",
"relationship": "self",
"evidence": []
}
}'The response is 201 Created with the full conversation snapshot. Keep the id — every subsequent call is scoped to it.
{
"id": "68d9a84d-711c-4a55-a9dd-da6363e58e38",
"status": "in_progress",
"settings": {
"language": "en",
"channel": "text",
"ui_widgets_enabled": false,
"opening_message_enabled": false,
"risk_factors_enabled": true,
"geographic_risk_factors_enabled": false,
"handoff_policies": [],
"max_message_length": 1500
},
"assessment": {
"age": { "value": 35, "unit": "year" },
"sex": "female",
"relationship": "self",
"evidence": [],
"unmatched_evidence": [],
"conditions": [],
"recommendation": null
},
"messages": [],
"is_terminated": false
}assessment is required, but everything inside it is optional. Send "assessment": {} when you have nothing to seed — omitting the object fails validation. Seed it whenever your host application already knows the patient: demographics supplied up front are questions the assistant does not have to ask.
2. Send a message
One user message produces one turn: the accepted input plus all assistant output it generated.
curl "https://api.infermedica.com/api/ct/v2/conversations/68d9a84d-711c-4a55-a9dd-da6363e58e38/turns" \
-X "POST" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"user_message": {
"content": "I have a headache"
}
}'The call blocks until the turn finishes and returns 201 Created:
{
"id": "a1b2c3d4-0000-0000-0000-000000000000",
"status": "completed",
"conversation_status": "in_progress",
"user_message": {
"id": "68d9a84d-711c-4a55-a9dd-da6363e58e38",
"content": "I have a headache"
},
"assistant_messages": [
{
"id": "6f605890-ff28-4b6d-a17f-d410f9faf558",
"turn_id": "a1b2c3d4-0000-0000-0000-000000000000",
"kind": "follow_up",
"can_interrupt": true,
"content_parts": [
{ "type": "text", "text": "How long have you had it?" }
]
}
],
"handoff": null,
"conversation_terminated": false
}Assistant text lives in content_parts, not in a top-level content field. To render plain text or feed a TTS engine, concatenate the text parts in order. See Messages and content parts.
3. Read the assessment
A blocking turn response deliberately omits the assessment. Refresh it with a separate read:
curl "https://api.infermedica.com/api/ct/v2/conversations/68d9a84d-711c-4a55-a9dd-da6363e58e38/assessment" \
-H "Authorization: Bearer <token>"{
"age": { "value": 35, "unit": "year" },
"sex": "female",
"relationship": "self",
"evidence": [
{
"id": "s_21",
"name": "Headache",
"common_name": "Headache",
"state": "present",
"origin": "asked",
"seriousness": "normal",
"parent_id": null
}
],
"unmatched_evidence": [],
"conditions": [],
"recommendation": null
}On the streaming transports you do not need this call — the assessment arrives on every turn as a conversation.assessment.updated event.
4. Continue until a recommendation
Repeat step 2 for each user message. Because the server owns the state, you never resend earlier evidence.
The conversation ends when assessment.recommendation becomes non-null and conversation_status flips to completed. At that point the recommendation carries the triage level, the specialist and channel suggestion, and the ranked differential conditions.
{
"recommendation": {
"triage_level": "consultation_24",
"conditions": [
{
"id": "c_49",
"probability": 0.4532,
"name": "Migraine",
"common_name": "Migraine",
"condition_details": { "...": "..." }
}
],
"has_emergency_evidence": false,
"serious_evidence": [],
"specialist": { "id": "sp_1", "name": "General practitioner" },
"channel": "personal_visit",
"stop_reason": "..."
}
}A conversation can also end without a recommendation — an underage patient or a confirmed change of age or sex set is_terminated to true, and further messages are rejected with conversation_terminated. The explanation for the user arrives in that turn's assistant messages. Handle both endings.
Next steps
- Conversation model — how conversations, turns, messages and the assessment relate to each other.
- Settings — language, voice channel, widgets, handoff detectors.
- Streaming turns and Realtime WebSocket — incremental output.
- Schemas — every wire shape, field by field.