Consultation documents
Retrieve summaries, SOAP notes, and clinician notes by ID, handle documents still generating, and render them safely.
When a consultation completes, the stream sends the IDs of its consultation documents. Retrieve each document by ID from your backend.
event: ai_consultation.complete
data: {"type":"ai_consultation.complete","artifacts":{"longSummary":"art_01K6JGGM2G2DB4Y9KB9H9MJJ6Q","shortSummary":"art_01K6JGGP7Q4R8S2T5V7W9X1Y3","soapNote":"art_01K6JGGR9Z6B2C4D6F8H0J2K4M"}}
curl "$DOCTRONIC_API_URL/artifacts/art_01K6JGGP7Q4R8S2T5V7W9X1Y3/" \
-H "Authorization: Bearer $DOCTRONIC_API_TOKEN" \
-H "X-Doctronic-User-ID: $DOCTRONIC_USER_ID"{
"code": "success",
"message": "Request successful",
"data": {
"artifactType": "short_summary",
"artifactId": "art_01K6JGGP7Q4R8S2T5V7W9X1Y3",
"content": {
"chatId": "chat_01K6JGGM2G2DB4Y9KB9H9MJJ6Q",
"createdAt": "2026-08-16T15:30:00Z",
"body": "## Consultation summary\n\n..."
}
}
}Artifact IDs
The ai_consultation.complete event carries an artifacts object. Each key holds a stable ID for
one consultation document. A key is absent or null when that document wasn't generated.
Store each non-null ID with the chat ID and the Doctronic user ID that received the event. A
document can still be generating when the event arrives; poll for it, or wait for the
artifact.ready webhook.
Document types
| Source | Key | artifactType | Document |
|---|---|---|---|
ai_consultation.complete | longSummary | long_summary | Long consultation summary |
ai_consultation.complete | shortSummary | short_summary | Short consultation summary |
ai_consultation.complete | soapNote | soap_note | AI-generated SOAP note |
| Appointment result | clinicianNote | clinician_note | Note finalized by the clinician after a visit |
The clinician note is a separate document from the AI-generated SOAP note. All four types use the same retrieval endpoint and response shape.
Retrieve a document
Send GET /artifacts/{artifactId}/
with the API token and the user ID that owns the chat. A ready response contains:
| Field | Contents |
|---|---|
data.artifactId | The ID you requested |
data.artifactType | One of the four types above |
data.content.chatId | The chat the document came from |
data.content.createdAt | ISO 8601 creation time |
data.content.body | The document as Markdown |
This helper retries while the document is generating and checks the chat before returning:
const baseUrl = process.env.DOCTRONIC_API_URL ?? 'https://staging-partners.doctronic.ai/api/v1';
export async function getArtifact(artifactId: string, userId: string, chatId: string) {
for (let attempt = 0; attempt < 6; attempt += 1) {
const response = await fetch(`${baseUrl}/artifacts/${artifactId}/`, {
headers: {
Authorization: `Bearer ${process.env.DOCTRONIC_API_TOKEN}`,
'X-Doctronic-User-ID': userId,
},
});
if (response.status === 200) {
const { data } = await response.json();
if (data.content.chatId !== chatId) throw new Error(`Artifact ${artifactId} belongs to another chat`);
return data;
}
if (response.status !== 202) throw new Error(`Artifact ${artifactId}: HTTP ${response.status}`);
await new Promise((resolve) => setTimeout(resolve, 2 ** attempt * 1000));
}
throw new Error(`Artifact ${artifactId} is still generating`);
}The attempt count and delays are example values. Set your own bounded policy.
Generation status
| Status | Meaning | Handling |
|---|---|---|
200 | The document is ready. | Check artifactType and content.chatId, then render or store content.body. |
202 | The document is still generating. | Retry with bounded backoff, or wait for artifact.ready. |
404 | error.artifact.not_found: the document is absent or outside your organization and user scope. The API reports both cases the same way. | Stop polling and check the stored user mapping. |
500 | Generation failed permanently. | Stop polling and show your failure path. |
Verify the chat
Before attaching a document to a local record, check that data.content.chatId matches the chat
whose completion event or appointment result supplied the ID. Keep the artifact ID and
createdAt alongside the rendered document so you can trace it to its source.
Render Markdown safely
Treat content.body as untrusted Markdown. Render it with a Markdown renderer that sanitizes
generated HTML and blocks scripts and embedded content.
Limits
- The
202response defines no body and no retry delay. - Documents are retrieved one at a time by ID; the API has no operation that lists them.