Patient Summary Generation
Generate Patient Summary For Specific Encounter
Trigger asynchronous generation of summaries for a specific encounter and practitioner from CKG data
Listen to this pageabout 2 min
POST
/
api
/
v1
/
patient-summary
/
generate
/
encounter
cURL
curl --request POST \
--url https://sdp.suki.ai/api/v1/patient-summary/generate/encounter \
--header 'Content-Type: application/json' \
--header 'sdp_suki_token: <sdp_suki_token>' \
--header 'sdp_provider_id: <sdp_provider_id>' \
--data '{"fhir_encounter_id":"enc-123","fhir_practitioner_id":"pract-456"}'import requests
import time
BASE_URL = "https://sdp.suki.ai"
sdp_token = "<sdp_suki_token>"
encounter_id = "enc-123"
practitioner_id = "pract-456"
# Step 1: Trigger generation
response = requests.post(
f"{BASE_URL}/api/v1/patient-summary/generate/encounter",
headers={"sdp_suki_token": sdp_token, "Content-Type": "application/json"},
json={"fhir_encounter_id": encounter_id, "fhir_practitioner_id": practitioner_id},
timeout=30
)
response.raise_for_status()
print(f"Generation triggered (Status: {response.status_code})")
# Step 2: Poll status until complete
status_url = f"{BASE_URL}/api/v1/patient-summary/encounter/{encounter_id}/practitioner/{practitioner_id}/status"
while True:
status_resp = requests.get(status_url, headers={"sdp_suki_token": sdp_token}, timeout=30)
status_data = status_resp.json()
print(f"Status: {status_data['status']}")
if status_data["status"] == "COMPLETED":
break
elif status_data["status"] == "FAILED":
raise Exception(f"Failed: {status_data.get('error')}")
time.sleep(5)
print("Generation completed successfully")const BASE_URL = "https://sdp.suki.ai";
const sdpToken = "<sdp_suki_token>";
const encounterId = "enc-123";
const practitionerId = "pract-456";
// Step 1: Trigger generation
const generateResponse = await fetch(
`${BASE_URL}/api/v1/patient-summary/generate/encounter`,
{
method: "POST",
headers: {
sdp_suki_token: sdpToken,
"Content-Type": "application/json",
},
body: JSON.stringify({
fhir_encounter_id: encounterId,
fhir_practitioner_id: practitionerId,
}),
}
);
if (!generateResponse.ok) {
throw new Error(`Generation failed: ${generateResponse.status}`);
}
console.log("Generation triggered");
// Step 2: Poll status until complete
const statusUrl = `${BASE_URL}/api/v1/patient-summary/encounter/${encounterId}/practitioner/${practitionerId}/status`;
while (true) {
const statusResponse = await fetch(statusUrl, {
headers: { sdp_suki_token: sdpToken },
});
const statusData = await statusResponse.json();
console.log(`Status: ${statusData.status}`);
if (statusData.status === "COMPLETED") {
break;
} else if (statusData.status === "FAILED") {
throw new Error(`Failed: ${statusData.error}`);
}
await new Promise((resolve) => setTimeout(resolve, 5000));
}
console.log("Generation completed successfully");<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sdp.suki.ai/api/v1/patient-summary/generate/encounter",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'fhir_encounter_id' => 'enc-123',
'fhir_practitioner_id' => 'pract-456'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"sdp_suki_token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sdp.suki.ai/api/v1/patient-summary/generate/encounter"
payload := strings.NewReader("{\n \"fhir_encounter_id\": \"enc-123\",\n \"fhir_practitioner_id\": \"pract-456\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("sdp_suki_token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sdp.suki.ai/api/v1/patient-summary/generate/encounter")
.header("sdp_suki_token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"fhir_encounter_id\": \"enc-123\",\n \"fhir_practitioner_id\": \"pract-456\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sdp.suki.ai/api/v1/patient-summary/generate/encounter")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["sdp_suki_token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"fhir_encounter_id\": \"enc-123\",\n \"fhir_practitioner_id\": \"pract-456\"\n}"
response = http.request(request)
puts response.read_body{
"patient_summary_id": "ee90d46e-1085-4a05-aa6a-1049113e857a"
}{
"code": 400,
"message": "invalid request"
}{
"code": 401,
"message": "invalid token"
}{
"code": 403,
"message": "forbidden"
}{
"code": 500,
"message": "internal server error"
}Use this endpoint to get the
Prerequisites:
After the request returns 201, call the Patient Summary retrieval endpoint with
patient_summary_id for a specific encounter and practitioner by providing the fhir_encounter_id and fhir_practitioner_id.
Once you have the patient_summary_id, use it to retrieve the generated summary via the Get full Patient Summary using Patient Summary ID endpoint.
When to call this endpoint
Call this endpoint after FHIR Patient, Encounter, and Practitioner resources for that visit are already in CKG. Generation does not upload clinical data. It starts an asynchronous job from data you already ingested. Use these request fields as follows:fhir_encounter_id: Required. Identifies the encounter in your ingested FHIR data. It must match the encounter identifier you uploaded.fhir_practitioner_id: Required. Identifies the practitioner in your ingested FHIR data. It must match the practitioner identifier you uploaded.
Patient summaries are generated from data previously ingested into the Clinical Knowledge Graph (CKG).
Before calling this endpoint, ensure the required Patient, Encounter, and Practitioner resources have been ingested using the CKG Data Ingestion APIs.
- Send Suki this data every morning (at midnight) for all appointments scheduled that day. This avoids waiting for the API to complete the generation process.
- Processing speed: Each individual appointment takes roughly 20 seconds to generate a Patient Summary once the API is triggered.
- Ingest the required Patient, Encounter, and Practitioner resources using the CKG Data Ingestion APIs.
- Include consistent patient, encounter, and practitioner identifiers in the FHIR resources.
- Ensure these identifiers match the
fhir_encounter_idandfhir_practitioner_idvalues you use for generation and retrieval.
Generation typically completes within a few seconds to a few minutes, depending on the amount of patient data available in the CKG.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
fhir_encounter_id | string | Yes | Encounter identifier. Must match the identifier in the ingested FHIR data. |
fhir_practitioner_id | string | Yes | Practitioner identifier. Must match the identifier in the ingested FHIR data. |
patient_summary_id (or use the encounter/practitioner retrieval path) to fetch the generated summary by using the following endpoints:
Authorizations
Suki access token (suki_token) from Login or Register. Expires after one hour.
Headers
Optional for standard partners.
Required for:
- Bearer authentication. Use the same
provider_idreturned by the Login or Register API. - Single Auth Token authentication. Include the same
provider_idon every request assdp_provider_id.
Example:
"provider-123"
Body
application/json
Response
Created. Summary generation request accepted and a patient summary resource was created.
Patient summary job ID returned from generate APIs.
Last modified on September 3, 2026
Was this page helpful?
cURL
curl --request POST \
--url https://sdp.suki.ai/api/v1/patient-summary/generate/encounter \
--header 'Content-Type: application/json' \
--header 'sdp_suki_token: <sdp_suki_token>' \
--header 'sdp_provider_id: <sdp_provider_id>' \
--data '{"fhir_encounter_id":"enc-123","fhir_practitioner_id":"pract-456"}'import requests
import time
BASE_URL = "https://sdp.suki.ai"
sdp_token = "<sdp_suki_token>"
encounter_id = "enc-123"
practitioner_id = "pract-456"
# Step 1: Trigger generation
response = requests.post(
f"{BASE_URL}/api/v1/patient-summary/generate/encounter",
headers={"sdp_suki_token": sdp_token, "Content-Type": "application/json"},
json={"fhir_encounter_id": encounter_id, "fhir_practitioner_id": practitioner_id},
timeout=30
)
response.raise_for_status()
print(f"Generation triggered (Status: {response.status_code})")
# Step 2: Poll status until complete
status_url = f"{BASE_URL}/api/v1/patient-summary/encounter/{encounter_id}/practitioner/{practitioner_id}/status"
while True:
status_resp = requests.get(status_url, headers={"sdp_suki_token": sdp_token}, timeout=30)
status_data = status_resp.json()
print(f"Status: {status_data['status']}")
if status_data["status"] == "COMPLETED":
break
elif status_data["status"] == "FAILED":
raise Exception(f"Failed: {status_data.get('error')}")
time.sleep(5)
print("Generation completed successfully")const BASE_URL = "https://sdp.suki.ai";
const sdpToken = "<sdp_suki_token>";
const encounterId = "enc-123";
const practitionerId = "pract-456";
// Step 1: Trigger generation
const generateResponse = await fetch(
`${BASE_URL}/api/v1/patient-summary/generate/encounter`,
{
method: "POST",
headers: {
sdp_suki_token: sdpToken,
"Content-Type": "application/json",
},
body: JSON.stringify({
fhir_encounter_id: encounterId,
fhir_practitioner_id: practitionerId,
}),
}
);
if (!generateResponse.ok) {
throw new Error(`Generation failed: ${generateResponse.status}`);
}
console.log("Generation triggered");
// Step 2: Poll status until complete
const statusUrl = `${BASE_URL}/api/v1/patient-summary/encounter/${encounterId}/practitioner/${practitionerId}/status`;
while (true) {
const statusResponse = await fetch(statusUrl, {
headers: { sdp_suki_token: sdpToken },
});
const statusData = await statusResponse.json();
console.log(`Status: ${statusData.status}`);
if (statusData.status === "COMPLETED") {
break;
} else if (statusData.status === "FAILED") {
throw new Error(`Failed: ${statusData.error}`);
}
await new Promise((resolve) => setTimeout(resolve, 5000));
}
console.log("Generation completed successfully");<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sdp.suki.ai/api/v1/patient-summary/generate/encounter",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'fhir_encounter_id' => 'enc-123',
'fhir_practitioner_id' => 'pract-456'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"sdp_suki_token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sdp.suki.ai/api/v1/patient-summary/generate/encounter"
payload := strings.NewReader("{\n \"fhir_encounter_id\": \"enc-123\",\n \"fhir_practitioner_id\": \"pract-456\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("sdp_suki_token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sdp.suki.ai/api/v1/patient-summary/generate/encounter")
.header("sdp_suki_token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"fhir_encounter_id\": \"enc-123\",\n \"fhir_practitioner_id\": \"pract-456\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sdp.suki.ai/api/v1/patient-summary/generate/encounter")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["sdp_suki_token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"fhir_encounter_id\": \"enc-123\",\n \"fhir_practitioner_id\": \"pract-456\"\n}"
response = http.request(request)
puts response.read_body{
"patient_summary_id": "ee90d46e-1085-4a05-aa6a-1049113e857a"
}{
"code": 400,
"message": "invalid request"
}{
"code": 401,
"message": "invalid token"
}{
"code": 403,
"message": "forbidden"
}{
"code": 500,
"message": "internal server error"
}