Seed Form Filling Session Context
Seed Form filling session context for a Form filling session using the Form filling URL binding
curl --request POST \
--url https://sdp.suki.ai/api/v1/form-filling/session/<ambient_session_id>/context \
--header 'Content-Type: application/json' \
--header 'sdp_suki_token: <sdp_suki_token>' \
--header 'sdp_provider_id: <sdp_provider_id>'import requests
url = "https://sdp.suki.ai/api/v1/form-filling/session/{ambient_session_id}/context"
payload = { "form_filling": { "values": [{ "form_template_id": "019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0" }, { "form_template_id": "019d4cdc-aaaa-bbbb-cccc-dddddddddddd" }] } }
headers = {
"sdp_suki_token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {sdp_suki_token: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
form_filling: {
values: [
{form_template_id: '019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0'},
{form_template_id: '019d4cdc-aaaa-bbbb-cccc-dddddddddddd'}
]
}
})
};
fetch('https://sdp.suki.ai/api/v1/form-filling/session/{ambient_session_id}/context', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sdp.suki.ai/api/v1/form-filling/session/{ambient_session_id}/context",
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([
'form_filling' => [
'values' => [
[
'form_template_id' => '019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0'
],
[
'form_template_id' => '019d4cdc-aaaa-bbbb-cccc-dddddddddddd'
]
]
]
]),
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/form-filling/session/{ambient_session_id}/context"
payload := strings.NewReader("{\n \"form_filling\": {\n \"values\": [\n {\n \"form_template_id\": \"019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0\"\n },\n {\n \"form_template_id\": \"019d4cdc-aaaa-bbbb-cccc-dddddddddddd\"\n }\n ]\n }\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/form-filling/session/{ambient_session_id}/context")
.header("sdp_suki_token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"form_filling\": {\n \"values\": [\n {\n \"form_template_id\": \"019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0\"\n },\n {\n \"form_template_id\": \"019d4cdc-aaaa-bbbb-cccc-dddddddddddd\"\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sdp.suki.ai/api/v1/form-filling/session/{ambient_session_id}/context")
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 \"form_filling\": {\n \"values\": [\n {\n \"form_template_id\": \"019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0\"\n },\n {\n \"form_template_id\": \"019d4cdc-aaaa-bbbb-cccc-dddddddddddd\"\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{}{
"code": 400,
"message": "invalid request"
}{
"code": 401,
"message": "invalid token"
}{
"code": 403,
"message": "forbidden"
}{
"code": 404,
"message": "not found"
}{
"code": 500,
"message": "internal server error"
}form_filling.values (either a form_template_id or a schema).
Suki lets you bind forms in the following ways:
- Static: A Suki Medical form template (
form_template_id) defined in the Suki Medical form templates catalog. - Dynamic: Your partner-defined
schemaobject (optionalid,name, andtype) for your own custom forms. - Mixed: Both static and dynamic entry types in the same
form_filling.valuesarray in case you need to capture a mix of Suki templates and your own custom forms.
form_filling with a non-empty values array in the request body. Each values[] entry must include exactly one of form_template_id or schema (never both) and be otherwise valid.Code examples
sdp.suki-stage.com only as examples.
For credentials, base URLs, where to run Python or TypeScript, CORS, and cURL, refer to Using code examples in your integration in the API Reference Guidelines.- Python
- TypeScript
from typing import Any, NotRequired, Optional, TypedDict, Union
import requests
BASE_URL = "https://sdp.suki-stage.com"
class StaticFormEntry(TypedDict):
# Suki Medical form template. Do not also send `schema` in this object.
form_template_id: str
class DynamicFormEntry(TypedDict):
# Partner-defined form. Do not also send `form_template_id` in this object.
schema: dict[str, Any]
id: NotRequired[str]
name: NotRequired[str]
type: NotRequired[str]
FormFillingMetadata = Union[StaticFormEntry, DynamicFormEntry]
class FormFillingContext(TypedDict):
# Non-empty list. Mix static and dynamic entries when needed.
values: list[FormFillingMetadata]
class FormFillingSessionContext(TypedDict, total=False):
# Session context. To generate filled forms, include `form_filling` with a non-empty `values` array.
# The request body MUST include `form_filling` when you expect filled form outputs.
form_filling: FormFillingContext
class ApiHttpError(RuntimeError):
def __init__(self, status: int, url: str, detail: str) -> None:
super().__init__(f"HTTP {status} {url}: {detail}")
self.status = status
self.url = url
def _post_json_expect(
url: str,
headers: dict[str, str],
payload: dict[str, Any],
expect_status: int,
) -> Optional[dict[str, Any]]:
r = requests.post(url, json=payload, headers=headers, timeout=60)
if r.status_code == expect_status:
# OpenAPI does not define a response body for 200 here, so treat it as optional.
if not r.text:
return None
try:
data = r.json()
except ValueError:
return None
return data if isinstance(data, dict) else None
detail = ""
try:
err = r.json()
if isinstance(err, dict) and isinstance(err.get("message"), str):
detail = err["message"]
except ValueError:
detail = (r.text or "")[:500]
raise ApiHttpError(r.status_code, url, detail or "(no body)")
def login_for_suki_token(partner_id: str, partner_token: str, *, provider_id: Optional[str] = None) -> str:
url = f"{BASE_URL}/api/v1/auth/login"
body: dict[str, Any] = {"partner_id": partner_id, "partner_token": partner_token}
if provider_id is not None:
body["provider_id"] = provider_id
r = requests.post(url, json=body, headers={"Content-Type": "application/json"}, timeout=60)
if r.status_code != 200:
raise ApiHttpError(r.status_code, url, (r.text or "")[:500] or "(no body)")
data = r.json()
token = data.get("suki_token") if isinstance(data, dict) else None
if not isinstance(token, str) or not token:
raise ValueError(f"{url}: 200 response missing suki_token")
return token
def seed_form_filling_session_context(
suki_token: str,
ambient_session_id: str,
body: Optional[FormFillingSessionContext] = None,
) -> None:
url = f"{BASE_URL}/api/v1/form-filling/session/{ambient_session_id}/context"
headers = {"sdp_suki_token": suki_token, "sdp_provider_id": "<sdp_provider_id>", "Content-Type": "application/json"}
_post_json_expect(url, headers, dict(body or {}), 200)
if __name__ == "__main__":
try:
token = login_for_suki_token("<partner_id>", "<partner_token>")
# The request body MUST include `form_filling` with a non-empty `values` array to generate filled forms.
# Each values[] entry must use either form_template_id or schema, never both.
seed_form_filling_session_context(
token,
ambient_session_id="<ambient_session_id>",
body={
"form_filling": {
"values": [
{"form_template_id": "019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0"},
{
"id": "partner-custom-1",
"name": "Custom Partner Form",
"type": "NEURO_ASSESSMENT",
"schema": {
"type": "object",
"properties": {"gcs": {"type": "number"}},
},
},
]
}
},
)
print("Context seeded.")
except (ApiHttpError, ValueError) as e:
print(e)
const BASE_URL = "https://sdp.suki-stage.com";
type AuthenticationRequest = {
partner_id: string;
partner_token: string;
provider_id?: string;
};
type AuthenticationResponse = { suki_token: string };
// Suki Medical form template. Do not also send `schema` in this object.
type StaticFormEntry = { form_template_id: string };
// Partner-defined form. Do not also send `form_template_id` in this object.
type DynamicFormEntry = {
schema: Record<string, unknown>;
id?: string;
name?: string;
type?: string;
};
type FormFillingMetadata = StaticFormEntry | DynamicFormEntry;
type FormFillingContext = { values: FormFillingMetadata[] }; // non-empty; mix allowed
type FormFillingSessionContext = {
// Optional. If present, `values` must be non-empty.
form_filling?: FormFillingContext;
};
async function postJsonExpectOptional(
url: string,
init: RequestInit,
expectStatus: number,
): Promise<{ json?: Record<string, unknown>; text?: string }> {
const res = await fetch(url, init);
const text = await res.text();
if (res.status !== expectStatus) {
let msg = text.slice(0, 500);
try {
const data: unknown = text ? JSON.parse(text) : null;
if (data && typeof data === "object" && "message" in data) {
msg = String((data as { message?: string }).message ?? msg);
}
} catch {
// keep raw text
}
throw new Error(`HTTP ${res.status} ${url}: ${msg || "(no body)"}`);
}
// OpenAPI does not define a response body for 200 here, so treat it as optional.
if (!text) return {};
try {
const data: unknown = JSON.parse(text);
if (data && typeof data === "object") return { json: data as Record<string, unknown>, text };
return { text };
} catch {
return { text };
}
}
async function loginForSukiToken(body: AuthenticationRequest): Promise<string> {
const url = `${BASE_URL}/api/v1/auth/login`;
const { json } = await postJsonExpectOptional(
url,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
},
200,
);
const token = json?.suki_token;
if (typeof token !== "string" || !token) throw new Error(`${url}: missing suki_token`);
return token;
}
async function seedFormFillingSessionContext(
sukiToken: string,
ambientSessionId: string,
body: FormFillingSessionContext = {},
): Promise<void> {
const url = `${BASE_URL}/api/v1/form-filling/session/${ambientSessionId}/context`;
await postJsonExpectOptional(
url,
{
method: "POST",
headers: {
sdp_suki_token: sukiToken, sdp_provider_id: "<sdp_provider_id>",
"Content-Type": "application/json",
},
body: JSON.stringify(body),
},
200,
);
}
async function main(): Promise<void> {
try {
const token = await loginForSukiToken({
partner_id: "<partner_id>",
partner_token: "<partner_token>",
});
// The request body MUST include `form_filling` with a non-empty `values` array to generate filled forms.
// Each values[] entry must use either form_template_id or schema, never both.
await seedFormFillingSessionContext(token, "<ambient_session_id>", {
form_filling: {
values: [
{ form_template_id: "019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0" },
{
id: "partner-custom-1",
name: "Custom Partner Form",
type: "NEURO_ASSESSMENT",
schema: {
type: "object",
properties: { gcs: { type: "number" } },
},
},
],
},
});
console.log("Context seeded.");
} catch (e) {
console.error(e instanceof Error ? e.message : e);
}
}
void main();
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.
"provider-123"
Path Parameters
Form-filling session ID. The path parameter is named ambient_session_id, but this value identifies the form-filling session, not an ambient clinical documentation session. Use the ID returned from Create Form filling Session, or the UUID you supplied in that request.
Body
Session context for Form filling. To enable form filling, include at least one entry in form_filling.values; each entry MUST include either form_template_id or schema. Seeding is required to generate filled forms.
Forms to fill for this session. Required only when you send context.
Show child attributes
Show child attributes
Response
Request succeeded.
The response is of type object.
Was this page helpful?
curl --request POST \
--url https://sdp.suki.ai/api/v1/form-filling/session/<ambient_session_id>/context \
--header 'Content-Type: application/json' \
--header 'sdp_suki_token: <sdp_suki_token>' \
--header 'sdp_provider_id: <sdp_provider_id>'import requests
url = "https://sdp.suki.ai/api/v1/form-filling/session/{ambient_session_id}/context"
payload = { "form_filling": { "values": [{ "form_template_id": "019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0" }, { "form_template_id": "019d4cdc-aaaa-bbbb-cccc-dddddddddddd" }] } }
headers = {
"sdp_suki_token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {sdp_suki_token: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
form_filling: {
values: [
{form_template_id: '019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0'},
{form_template_id: '019d4cdc-aaaa-bbbb-cccc-dddddddddddd'}
]
}
})
};
fetch('https://sdp.suki.ai/api/v1/form-filling/session/{ambient_session_id}/context', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sdp.suki.ai/api/v1/form-filling/session/{ambient_session_id}/context",
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([
'form_filling' => [
'values' => [
[
'form_template_id' => '019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0'
],
[
'form_template_id' => '019d4cdc-aaaa-bbbb-cccc-dddddddddddd'
]
]
]
]),
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/form-filling/session/{ambient_session_id}/context"
payload := strings.NewReader("{\n \"form_filling\": {\n \"values\": [\n {\n \"form_template_id\": \"019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0\"\n },\n {\n \"form_template_id\": \"019d4cdc-aaaa-bbbb-cccc-dddddddddddd\"\n }\n ]\n }\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/form-filling/session/{ambient_session_id}/context")
.header("sdp_suki_token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"form_filling\": {\n \"values\": [\n {\n \"form_template_id\": \"019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0\"\n },\n {\n \"form_template_id\": \"019d4cdc-aaaa-bbbb-cccc-dddddddddddd\"\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sdp.suki.ai/api/v1/form-filling/session/{ambient_session_id}/context")
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 \"form_filling\": {\n \"values\": [\n {\n \"form_template_id\": \"019d4cdc-9319-7d81-ae2e-fd6de7f1b4f0\"\n },\n {\n \"form_template_id\": \"019d4cdc-aaaa-bbbb-cccc-dddddddddddd\"\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{}{
"code": 400,
"message": "invalid request"
}{
"code": 401,
"message": "invalid token"
}{
"code": 403,
"message": "forbidden"
}{
"code": 404,
"message": "not found"
}{
"code": 500,
"message": "internal server error"
}