API v1 · Reference

POST /v1/soap

One-call SOAP intake. Submit a finished transcript or the consultation audio, and the platform queues the full pipeline: structured SOAP note, ICD-10 candidates matched from the curated code table, WHO/IMCI-aligned triage and the NHIS billing proposal.

What one call produces

Everything below is generated from the consultation alone — no invented facts, no demographic inferences.

Structured SOAP note

Subjective, Objective, Assessment and Plan drafted from strictly validated, evidence-grounded facts extracted from the consultation.

ICD-10 candidates

Codes matched programmatically from the curated ICD-10-CM table, each with the concept and verbatim note phrases that produced it. The model never invents a code.

WHO / IMCI triage

Deterministic, offline triage over the transcript and note: general danger signs, matching WHO and national protocols, ordered next steps and notifiable-disease flags.

NHIS billing proposal

Claim items tagged by scheme with coverage notes, plus claim-readiness checks that flag the usual denial reasons before filing.

Request format

Required scope: transcription.create. Send either a JSON transcript or a multipart audio upload — never both.

FieldRequiredDescription
transcriptJSON onlyThe consultation transcript, 20–100,000 characters. Use this when your app already holds text (telemedicine chat, typed notes, a completed streaming session).
audioMultipart onlyThe consultation recording as multipart field `audio`. Max 60 MB. Accepted types: audio/webm, ogg, wav, mpeg, mp4, m4a, flac. Audio is stored in the partner bucket only and deleted once transcription finishes.
external_consultation_idRequired for audio; recommended alwaysYour own encounter reference (≤128 chars). It is the idempotency key: resubmitting the same reference returns the existing job instead of creating a duplicate encounter. Omitted values are auto-generated.
encounter_typeNoOne of outpatient (default), inpatient, telehealth, emergency, follow_up.
languageNoBCP-47 style code for the consultation language — en, yo, ha, sw, pcm. Amharic (am) and Oromo (om) are in beta. Improves transcription and terminology handling.
specialtyNoA specialty engine id from GET /specialties (behavioural health, refugee/immigrant health, PT, OT and core specialties). Shapes note structure and vocabulary only; never adds facts.
external_patient_idNoYour own opaque patient reference (≤128 chars). Never a name, phone number or medical record number. Defaults to "unspecified".
external_clinician_idNoYour own opaque clinician reference (≤128 chars). Defaults to "unspecified".
age_groupNoOne of infant, child, adult (default), elderly. Selects the correct WHO/IMCI protocol set for triage. The API never infers age from the transcript — pass it when you know it.
pregnantNoBoolean, default false. Applies pregnancy-specific triage protocols (for example pre-eclampsia and malaria-in-pregnancy pathways).
JSON — submit a transcript
curl -X POST https://gelypticmd.com/api/public/v1/soap \
  -H "Authorization: Bearer $GELYPTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_consultation_id": "clinic-4821",
    "encounter_type": "outpatient",
    "language": "pcm",
    "age_group": "child",
    "transcript": "Doctor: Wetin dey worry am? Mother: the pikin dey purge since yesterday and e no fit feed..."
  }'

# -> 202 Accepted
# {
#   "encounter_id": "b0f1c2d3-...",
#   "job_id": "JOB-9F2C4B1E8A7D4C2F",
#   "status": "processing"
# }
Multipart — submit encounter audio
curl -X POST https://gelypticmd.com/api/public/v1/soap \
  -H "Authorization: Bearer $GELYPTIC_API_KEY" \
  -F "external_consultation_id=clinic-4821" \
  -F "encounter_type=outpatient" \
  -F "language=yo" \
  -F "age_group=adult" \
  -F "audio=@consultation.webm"

Response

The request is accepted synchronously; the AI work never runs inline.

202 Accepted
{
  "encounter_id": "b0f1c2d3-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
  "job_id": "JOB-9F2C4B1E8A7D4C2F",
  "status": "processing"
}
encounter_id
The platform encounter id. Use it with GET /clinical/notes/{encounter_id} once the note is drafted.
job_id
Pollable via GET /jobs/{job_id}. Queued → Processing → Completed/Failed.
x-request-id
Every response carries a request id header; quote it when contacting support.
Idempotency
Re-submitting the same external_consultation_id returns 200 with the current job state and idempotent: true — no duplicate encounter is created.
Errors
400 INVALID_REQUEST (bad payload), 401 (missing/invalid key), 403 (scope missing), 413 PAYLOAD_TOO_LARGE, 429 RATE_LIMITED, 500 INTERNAL_ERROR.
Idempotent repeat (200)
{
  "encounter_id": "b0f1c2d3-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
  "job_id": "JOB-9F2C4B1E8A7D4C2F",
  "status": "PROCESSING",
  "idempotent": true
}

Receiving the result

Two delivery options. Use the webhook in production; polling is the fallback.

Signed webhook — soap.generated (simplified)
{
  "id": "evt_01H…",
  "type": "soap.generated",
  "created_at": "2026-10-06T22:41:07Z",
  "api_version": "v1",
  "data": {
    "consultation_id": "b0f1c2d3-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
    "external_consultation_id": "clinic-4821",
    "job_id": "JOB-9F2C4B1E8A7D4C2F",
    "status": "draft",
    "fhir_bundle": { "resourceType": "Bundle", "type": "collection", "entry": [ "..." ] },
    "icd10_suggestions": [
      {
        "concept": "uncomplicated malaria",
        "codes": [ { "code": "B54", "title": "Unspecified malaria" } ]
      }
    ],
    "triage": {
      "level": "priority",
      "danger_signs": [],
      "actions": [ "Do a malaria RDT before starting treatment." ],
      "notifiable": false
    },
    "billing": {
      "scheme": "NHIS",
      "claim_items": [
        { "id": "mrdt", "label": "Malaria rapid diagnostic test",
          "note": "Reimbursable diagnostic. Attach the result value to avoid a denial." }
      ],
      "claim_checks": [
        { "id": "diagnosis", "label": "A codable diagnosis is documented",
          "passed": true, "detail": "1 ICD-10 candidate(s) found." }
      ]
    }
  }
}
Fallback — poll the job
curl https://gelypticmd.com/api/public/v1/jobs/JOB-9F2C4B1E8A7D4C2F \
  -H "Authorization: Bearer $GELYPTIC_API_KEY"

# {
#   "job_id": "JOB-9F2C4B1E8A7D4C2F",
#   "consultation_id": "b0f1c2d3-...",
#   "status": "COMPLETED",
#   "detail_status": "drafted",
#   "updated_at": "2026-10-06T22:41:07Z"
# }

Webhook deliveries are HMAC-signed over {timestamp}.{rawBody} and carry an x-scribemd-signature header — verify them exactly as shown in webhooks. Once completed, fetch the full note — including the complete triage and billing structures — with GET /clinical/notes/{encounter_id}.

Response structure reference

soap_note

subjective
Reported symptoms and history, in the patient's own framing after terminology normalisation. Never contains age, sex or other demographics.
objective
Only stated examination findings; otherwise a fixed placeholder sentence.
assessment
Clinical impression phrased as suggestions when not confirmed in the consultation.
plan
Only items discussed in the consultation; otherwise a fixed placeholder sentence.
state
Always "draft" until a clinician approves the note; "approved" afterwards. Drafts are never presented as signed clinical records.

icd10_suggestions

concept
A plain clinical concept to code, extracted from the transcript with verbatim evidence.
codes
Matching ICD-10-CM entries from the curated code table (code and title). Empty when no confident match exists — candidates are never guessed.

triage

level
One of emergency, urgent, priority, routine. A WHO general danger sign always forces emergency.
danger_signs
The WHO/IMCI general danger signs matched in the consultation (for example convulsion, unable to drink or feed, vomiting everything).
protocols
Matching WHO and national protocols with source, matched triggers, ordered actions, confirmatory tests and explicit cautions. Age-specific protocols apply only when age_group was supplied.
actions
Ordered, deduplicated next steps for the clinician.
notifiable
True when a protocol matches a notifiable disease (for example suspected VHF, measles or meningitis) and your surveillance programme should be alerted.

billing

scheme
Currently "NHIS". Claim items carry per-scheme coverage notes from NHIS Nigeria and NHIF Kenya practice.
claim_items
Proposed billable items: id, label, scheme and a note on bundling or documentation the scheme normally requires.
claim_checks
Claim-readiness checks — codable diagnosis, documented indication for investigations, a management plan, clinician review recorded, referral authorisation code, capitation double-billing. Each check carries passed and an explanatory detail.
Nothing is auto-submitted
Billing output is a proposal for the clinician or biller to confirm. GELYPTIC MD never files a claim or charges an insurer.

Working example, end to end

Node 18+ — submit and consume the webhook
import crypto from "node:crypto";

// 1. Submit the consultation — one call.
const submit = await fetch("https://gelypticmd.com/api/public/v1/soap", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.GELYPTIC_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    external_consultation_id: "clinic-4821",
    language: "pcm",
    age_group: "child",
    transcript: consultationTranscript,
  }),
});
const { encounter_id, job_id } = await submit.json();

// 2. Verify and consume the signed soap.generated webhook.
app.post("/gelyptic/webhooks", (req, res) => {
  const raw = rawBodyOf(req);            // the exact bytes that arrived
  const parts = Object.fromEntries(
    (req.headers["x-scribemd-signature"] ?? "").split(",").map((p) => p.split("=")),
  );
  const expected = crypto
    .createHmac("sha256", process.env.GELYPTIC_WEBHOOK_SECRET)
    .update(`${parts.t}.${raw}`)
    .digest("hex");

  const a = Buffer.from(parts.v1 ?? "", "hex");
  const b = Buffer.from(expected, "hex");
  const ok = a.length === b.length && crypto.timingSafeEqual(a, b)
    && Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;

  if (!ok) return res.sendStatus(401);
  if (req.body.type === "soap.generated") {
    saveNote(req.body.data);             // store the draft, queue clinician review
  }
  res.sendStatus(200);
});
Python — submit
import os, requests

res = requests.post(
    "https://gelypticmd.com/api/public/v1/soap",
    headers={"Authorization": f"Bearer {os.environ['GELYPTIC_API_KEY']}"},
    json={
        "external_consultation_id": "clinic-4821",
        "language": "pcm",
        "age_group": "child",
        "transcript": consultation_transcript,
    },
    timeout=30,
)
res.raise_for_status()
job = res.json()          # {"encounter_id": ..., "job_id": ..., "status": "processing"}
print(job["job_id"])

The typed SDKs wrap this endpoint: client.submitSoap({ transcript, externalConsultationId }) in TypeScript and client.submit_soap(transcript=…, external_consultation_id=…) in Python.

Clinical safety and data boundaries

Clinician review is not bypassable
Every generated note is a draft. Your application must present it for clinician approval before it becomes a clinical record, and interoperability exports are only produced after approval.
No demographics
The pipeline never mentions or infers age, sex, gender, race or ethnicity in generated notes. The age_group and pregnant fields only select triage protocols and are stored as coarse context, never copied into notes.
Your records only
Encounters filed through /soap belong to the calling application. There is no cross-tenant read path, and GELYPTIC MD clinician consultations are unreachable through the API.
Browser session tokens cannot call /soap
Session tokens are scope-reduced to embedded upload and read scopes. Only a server-held API key can create encounters and generate notes.
No compliance claim
These are security controls we implement — they are not, by themselves, a regulatory compliance certification.