> ## Documentation Index
> Fetch the complete documentation index at: https://developer.suki.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# E/M Coding API Quickstart

> Authenticate, start a standalone E/M coding session, poll status, and retrieve codes

This quickstart walks you through one successful standalone E/M Coding workflow: authenticate, submit note sections, poll status, and retrieve generated codes.

Your application owns when coding runs, how you map codes into RCM or EHR handoff, and whether you poll or use the webhook.

**What you will do**

1. **Authenticate** to get an `sdp_suki_token` (and **register** the user if needed).
2. **Start** a standalone E/M coding session with note sections.
3. **Poll** status until `completed` or `failed`.
4. **Retrieve** the generated E/M codes.

> [!TIP]
>
> **Prefer one paste-ready file?** Use the [Complete script](#complete-script) in the preferred language below, then follow the numbered steps for the same flow with full explanations.

> [!TIP]
>
> **Using an AI coding tool?**
>
> Copy the prompt below to point your agent at the E/M Coding API skill and [Documentation MCP](https://developer.suki.ai/documentation/references/mcp.md). For every task skill, refer to [AI coding tools](https://developer.suki.ai/documentation/references/ai-coding-tools.md).
>
> Fetch the E/M Coding API skill and connect the documentation MCP.
>
> Build E/M Coding with Suki for Partners.
> Fetch the E/M Coding API skill:
> [https://developer.suki.ai/.well-known/agent-skills/suki-em-coding-api/SKILL.md](https://developer.suki.ai/.well-known/agent-skills/suki-em-coding-api/SKILL.md)
> Connect the documentation MCP for page search:
> [https://developer.suki.ai/documentation/references/mcp](https://developer.suki.ai/documentation/references/mcp.md)

## Access and credentials

You need partner credentials to use the Suki E/M Coding APIs.

Contact our [Partnership team](https://www.suki.ai/contact-us/) to get your credentials. They will guide you through the [Onboarding process](https://developer.suki.ai/documentation/get-started/partner-onboarding.md), confirm that E/M Coding is enabled for your organization, and provide what you need to get started.

### Prerequisites

To use the Suki E/M Coding APIs, you must have the following:

* Partner credentials for Suki authentication endpoints (`partner_id` and `partner_token`).
* Ability to call Login (and Register when needed) to obtain an `sdp_suki_token`.
* Note section text (LOINC + content) for at least one section.
* Optional but recommended for better codes: patient type, date of service, diagnoses, insurance, provider NPI, and total time minutes when billing by time.
* A publicly accessible JWKS (JSON Web Key Set. A set of keys containing the public keys used to verify any JWT issued by the authorization server.) endpoint (or Okta authorization server) for token validation.

### Environments to use for development and testing

Examples use **`https://sdp.suki.ai`** for API calls (production).

**Important**:

* The production environment is **`https://sdp.suki.ai`**.
* The staging environment is **`https://sdp.suki-stage.com`**.
* Your partnership team will confirm which environment, base URL, and credentials apply for your integration.

## Complete script

Replace the credential placeholders, then run. For detailed explanations of each step, refer to the numbered steps below.

* **Python:** `pip install requests` then `python em_coding.py`.
* **TypeScript (Node):** `npx tsx em_coding.ts` (Node 18+).

```python Python expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
# em_coding.py
# Flow: login (register once if needed) → POST /em-codes → poll status → GET codes
# pip install requests

import json
import time
from typing import Any, Optional

import requests

BASE_URL = "https://sdp.suki.ai"

PARTNER_ID = "your-partner-id"
PARTNER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."  # Keep on your backend only
PROVIDER_ID = "provider-123"  # Optional; required for some auth flows
SDP_PROVIDER_ID = ""  # Leave empty unless your partnership requires sdp_provider_id


def expect_status(response: requests.Response, url: str, want: int) -> None:
    if response.status_code == want:
        return
    detail = (response.text or "")[:500]
    try:
        body = response.json()
        if isinstance(body, dict) and body.get("message"):
            detail = str(body["message"])
    except ValueError:
        pass
    raise RuntimeError(f"HTTP {response.status_code} {url}: {detail}")


def login(partner_id: str, partner_token: str, provider_id: Optional[str] = None) -> str:
    url = f"{BASE_URL}/api/v1/auth/login"
    payload: dict[str, Any] = {"partner_id": partner_id, "partner_token": partner_token}
    if provider_id:
        payload["provider_id"] = provider_id
    response = requests.post(url, json=payload, timeout=60)
    expect_status(response, url, 200)
    token = response.json().get("suki_token")
    if not token:
        raise RuntimeError("login response missing suki_token")
    return token


def register_provider(
    partner_id: str,
    partner_token: str,
    provider_name: str,
    provider_org_id: str,
    provider_id: Optional[str] = None,
) -> None:
    url = f"{BASE_URL}/api/v1/auth/register"
    payload: dict[str, Any] = {
        "partner_id": partner_id,
        "partner_token": partner_token,
        "provider_name": provider_name,
        "provider_org_id": provider_org_id,
    }
    if provider_id:
        payload["provider_id"] = provider_id
    response = requests.post(url, json=payload, timeout=60)
    # New link: 201. Already linked: 409. Both are success for this flow.
    if response.status_code not in (201, 409):
        expect_status(response, url, 201)


def login_with_register_fallback(
    partner_id: str,
    partner_token: str,
    provider_id: Optional[str],
    provider_name: str,
    provider_org_id: str,
) -> str:
    try:
        return login(partner_id, partner_token, provider_id)
    except RuntimeError as err:
        if "provider_not_registered" not in str(err):
            raise
        register_provider(
            partner_id, partner_token, provider_name, provider_org_id, provider_id
        )
        return login(partner_id, partner_token, provider_id)


def rest_headers(suki_token: str) -> dict[str, str]:
    headers = {
        "sdp_suki_token": suki_token,
        "Content-Type": "application/json",
    }
    if SDP_PROVIDER_ID:
        headers["sdp_provider_id"] = SDP_PROVIDER_ID
    return headers


def generate_em_codes(suki_token: str) -> str:
    url = f"{BASE_URL}/api/v1/em-codes"
    payload = {
        "sections": [
            {
                "loinc": "10164-2",
                "content": {
                    "type": "TEXT",
                    "text": (
                        "Established patient with hypertension. "
                        "Medication adjusted. Follow-up planned."
                    ),
                },
            }
        ],
        "patient": {
            "dob": "1952-03-15",
            "sex": "female",
            "patient_type": "ESTABLISHED_PATIENT",
        },
        "encounter": {
            "date_of_service": "2026-01-15",
            "total_time_minutes": 30,
            "visit_type": "ESTABLISHED_PATIENT",
        },
    }
    response = requests.post(url, headers=rest_headers(suki_token), json=payload, timeout=60)
    expect_status(response, url, 201)
    session_id = response.json().get("session_id")
    if not session_id:
        raise RuntimeError("Generate response missing session_id")
    return session_id


def poll_status(suki_token: str, session_id: str, timeout_s: int = 180) -> str:
    url = f"{BASE_URL}/api/v1/em-codes/{session_id}/status"
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        response = requests.get(url, headers=rest_headers(suki_token), timeout=60)
        expect_status(response, url, 200)
        status = response.json().get("status")
        print(f"E/M coding status: {status}")
        if status in ("completed", "failed"):
            return status
        time.sleep(3)
    raise TimeoutError(f"Timed out waiting for E/M coding session {session_id}")


def get_codes(suki_token: str, session_id: str) -> dict[str, Any]:
    url = f"{BASE_URL}/api/v1/em-codes/{session_id}"
    response = requests.get(url, headers=rest_headers(suki_token), timeout=60)
    expect_status(response, url, 200)
    return response.json()


def main() -> None:
    print("Step 1: Authenticate")
    suki_token = login_with_register_fallback(
        PARTNER_ID,
        PARTNER_TOKEN,
        PROVIDER_ID,
        "Dr. Jane Smith",
        "org-456",
    )
    print("Authenticated")

    print("Step 2: Start E/M coding")
    session_id = generate_em_codes(suki_token)
    print(f"session_id={session_id}")

    print("Step 3: Poll status")
    status = poll_status(suki_token, session_id)
    if status != "completed":
        raise RuntimeError(f"Coding ended with status={status}")

    print("Step 4: Retrieve E/M codes")
    codes = get_codes(suki_token, session_id)
    print(json.dumps(codes, indent=2))


if __name__ == "__main__":
    main()
```

```typescript TypeScript expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
// em_coding.ts
// Flow: login (register once if needed) → POST /em-codes → poll status → GET codes
// npx tsx em_coding.ts

const BASE_URL = "https://sdp.suki.ai";

const PARTNER_ID = "your-partner-id";
const PARTNER_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."; // Keep on your backend only
const PROVIDER_ID = "provider-123"; // Optional; required for some auth flows
const SDP_PROVIDER_ID = ""; // Leave empty unless your partnership requires sdp_provider_id

async function expectStatus(res: Response, url: string, want: number): Promise<any> {
  const text = await res.text();
  let body: any = {};
  try {
    body = text ? JSON.parse(text) : {};
  } catch {
    body = { raw: text };
  }
  if (res.status !== want) {
    const detail =
      typeof body?.message === "string" ? body.message : text.slice(0, 500);
    throw new Error(`HTTP ${res.status} ${url}: ${detail}`);
  }
  return body;
}

function restHeaders(sukiToken: string): Record<string, string> {
  const headers: Record<string, string> = {
    sdp_suki_token: sukiToken,
    "Content-Type": "application/json",
  };
  if (SDP_PROVIDER_ID) headers.sdp_provider_id = SDP_PROVIDER_ID;
  return headers;
}

async function login(
  partnerId: string,
  partnerToken: string,
  providerId?: string,
): Promise<string> {
  const url = `${BASE_URL}/api/v1/auth/login`;
  const body: Record<string, string> = {
    partner_id: partnerId,
    partner_token: partnerToken,
  };
  if (providerId) body.provider_id = providerId;

  const response = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const data = await expectStatus(response, url, 200);
  if (!data.suki_token) throw new Error("login response missing suki_token");
  return data.suki_token;
}

async function registerProvider(input: {
  partnerId: string;
  partnerToken: string;
  providerName: string;
  providerOrgId: string;
  providerId?: string;
}): Promise<void> {
  const url = `${BASE_URL}/api/v1/auth/register`;
  const body: Record<string, string> = {
    partner_id: input.partnerId,
    partner_token: input.partnerToken,
    provider_name: input.providerName,
    provider_org_id: input.providerOrgId,
  };
  if (input.providerId) body.provider_id = input.providerId;

  const response = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  if (response.status !== 201 && response.status !== 409) {
    await expectStatus(response, url, 201);
  }
}

async function loginWithRegisterFallback(
  partnerId: string,
  partnerToken: string,
  providerId: string | undefined,
  providerName: string,
  providerOrgId: string,
): Promise<string> {
  try {
    return await login(partnerId, partnerToken, providerId);
  } catch (err) {
    if (!String(err).includes("provider_not_registered")) throw err;
    await registerProvider({
      partnerId,
      partnerToken,
      providerName,
      providerOrgId,
      providerId,
    });
    return login(partnerId, partnerToken, providerId);
  }
}

async function generateEmCodes(sukiToken: string): Promise<string> {
  const url = `${BASE_URL}/api/v1/em-codes`;
  const payload = {
    sections: [
      {
        loinc: "10164-2",
        content: {
          type: "TEXT",
          text: "Established patient with hypertension. Medication adjusted. Follow-up planned.",
        },
      },
    ],
    patient: {
      dob: "1952-03-15",
      sex: "female",
      patient_type: "ESTABLISHED_PATIENT",
    },
    encounter: {
      date_of_service: "2026-01-15",
      total_time_minutes: 30,
      visit_type: "ESTABLISHED_PATIENT",
    },
  };
  const data = await expectStatus(
    await fetch(url, {
      method: "POST",
      headers: restHeaders(sukiToken),
      body: JSON.stringify(payload),
    }),
    url,
    201,
  );
  if (!data.session_id) throw new Error("Generate response missing session_id");
  return data.session_id;
}

async function pollStatus(
  sukiToken: string,
  sessionId: string,
  timeoutMs = 180_000,
): Promise<string> {
  const url = `${BASE_URL}/api/v1/em-codes/${sessionId}/status`;
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const data = await expectStatus(
      await fetch(url, { headers: restHeaders(sukiToken) }),
      url,
      200,
    );
    console.log("E/M coding status:", data.status);
    if (data.status === "completed" || data.status === "failed") return data.status;
    await new Promise((r) => setTimeout(r, 3000));
  }
  throw new Error(`Timed out waiting for E/M coding session ${sessionId}`);
}

async function getCodes(sukiToken: string, sessionId: string): Promise<unknown> {
  const url = `${BASE_URL}/api/v1/em-codes/${sessionId}`;
  return expectStatus(await fetch(url, { headers: restHeaders(sukiToken) }), url, 200);
}

async function main() {
  console.log("Step 1: Authenticate");
  const sukiToken = await loginWithRegisterFallback(
    PARTNER_ID,
    PARTNER_TOKEN,
    PROVIDER_ID,
    "Dr. Jane Smith",
    "org-456",
  );
  console.log("Authenticated");

  console.log("Step 2: Start E/M coding");
  const sessionId = await generateEmCodes(sukiToken);
  console.log("session_id:", sessionId);

  console.log("Step 3: Poll status");
  const status = await pollStatus(sukiToken, sessionId);
  if (status !== "completed") throw new Error(`Coding ended with status=${status}`);

  console.log("Step 4: Retrieve E/M codes");
  console.log(JSON.stringify(await getCodes(sukiToken, sessionId), null, 2));
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
```

## Create your first E/M coding session

**1. Authenticate to Get a Suki Token**

To begin, you must authenticate to get your access token. Send a **POST** request to the [Login API](https://developer.suki.ai/em-coding-api-reference/authentication/login.md) endpoint with the following parameters in the request body:

* **partner\_id**: Your unique Partner ID (A unique identifier assigned by Suki during onboarding that links an application to its configuration in the Suki Developer Platform.), which we provide to you securely offline.
* **partner\_token**: The user's OAuth 2.0 ID token (Partner Token (A secure, digitally signed JWT issued by a partner's identity provider after user authentication, passed to Suki SDK for user verification.)) from your identity provider.
* **provider\_id** (Optional): Unique identifier for the provider (A healthcare professional such as a physician, APP, or nurse who documents care. In Suki integrations, provider identity ties sessions, preferences, and generated notes to the correct clinician.). Required for Bearer type partners only.

On a successful request, the API returns a Suki Token (The access token returned by Suki's authentication API, used to authorize subsequent API requests to the Suki platform.) (`suki_token`) that you must include as the `sdp_suki_token` header for all subsequent API calls.

> [!NOTE]
>
> **Handling an unregistered user**:
>
> * If the user is not yet registered in our system, the `/login` request will fail.
> * In this case, you must first call the [Register API](https://developer.suki.ai/em-coding-api-reference/authentication/register.md) endpoint to create the user, then call `/login` again.
> * You only need to call the register endpoint once for each new user.

```typescript TypeScript expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
const BASE_URL = "https://sdp.suki.ai";

const response = await fetch(`${BASE_URL}/api/v1/auth/login`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    partner_id: "your-partner-id",
    partner_token: "your-jwt-token",
    provider_id: "provider-123", // Omit if not required
  }),
});

const data = await response.json();
if (!response.ok) {
  throw new Error(`Login failed: ${response.status} ${JSON.stringify(data)}`);
}
if (!data.suki_token) throw new Error("login response missing suki_token");
console.log("suki_token:", data.suki_token);
```

```python Python expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
import requests

BASE_URL = "https://sdp.suki.ai"

response = requests.post(
    f"{BASE_URL}/api/v1/auth/login",
    json={
        "partner_id": "your-partner-id",
        "partner_token": "your-jwt-token",
        "provider_id": "provider-123",  # Omit if not required
    },
    timeout=60,
)
if response.status_code != 200:
    raise RuntimeError(f"Login failed: {response.status_code} {response.text}")
print("suki_token:", response.json()["suki_token"])
```

```bash cURL expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
curl --request POST \
  --url https://sdp.suki.ai/api/v1/auth/login \
  --header 'Content-Type: application/json' \
  --data '{
    "partner_id": "your-partner-id",
    "partner_token": "your-jwt-token",
    "provider_id": "provider-123"
  }'
```

> [!TIP]
>
> Save the `suki_token` from the response. This token is valid for **1 hour**. When it is about to expire, you can get a new one by making the same **POST** request to `/login` with a valid `partner_token`.

**2. Start Standalone E/M Coding**

Call the [Generate E/M codes](https://developer.suki.ai/em-coding-api-reference/em-coding-sessions/generate.md) endpoint with note `sections` (required) and optional patient, provider, encounter, and diagnoses context.

* **sections** (required): At least one LOINC section with `content.type` set to `TEXT` and non-empty `content.text`.
* **patient**, **provider**, **encounter**, **diagnoses** (optional): Improve code selection when you have them. Include `patient_type`, `date_of_service`, and `total_time_minutes` when billing by time.

Suki returns an E/M coding `session_id`. Generation is asynchronous.

> [!NOTE]
>
> The `session_id` returned here is an **E/M coding session ID**. It is not an ambient session ID. Use it only with the E/M status and retrieve endpoints.

```typescript TypeScript expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
const BASE_URL = "https://sdp.suki.ai";
const sukiToken = "<sdp_suki_token from login>";
const sdpProviderId = ""; // Set only if required

const headers: Record<string, string> = {
  "Content-Type": "application/json",
  sdp_suki_token: sukiToken,
};
if (sdpProviderId) headers.sdp_provider_id = sdpProviderId;

const generateResponse = await fetch(`${BASE_URL}/api/v1/em-codes`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    sections: [
      {
        loinc: "10164-2",
        content: {
          type: "TEXT",
          text: "Established patient with hypertension. Medication adjusted. Follow-up planned.",
        },
      },
    ],
    patient: {
      dob: "1952-03-15",
      sex: "female",
      patient_type: "ESTABLISHED_PATIENT",
    },
    encounter: {
      date_of_service: "2026-01-15",
      total_time_minutes: 30,
      visit_type: "ESTABLISHED_PATIENT",
    },
  }),
});
const generated = await generateResponse.json();
if (generateResponse.status !== 201) {
  throw new Error(`Generate failed: ${generateResponse.status} ${JSON.stringify(generated)}`);
}
console.log("session_id:", generated.session_id);
```

```python Python expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
import requests

BASE_URL = "https://sdp.suki.ai"
suki_token = "<sdp_suki_token from login>"
sdp_provider_id = ""  # Set only if required

headers = {
    "sdp_suki_token": suki_token,
    "Content-Type": "application/json",
}
if sdp_provider_id:
    headers["sdp_provider_id"] = sdp_provider_id

generate_response = requests.post(
    f"{BASE_URL}/api/v1/em-codes",
    headers=headers,
    json={
        "sections": [
            {
                "loinc": "10164-2",
                "content": {
                    "type": "TEXT",
                    "text": (
                        "Established patient with hypertension. "
                        "Medication adjusted. Follow-up planned."
                    ),
                },
            }
        ],
        "patient": {
            "dob": "1952-03-15",
            "sex": "female",
            "patient_type": "ESTABLISHED_PATIENT",
        },
        "encounter": {
            "date_of_service": "2026-01-15",
            "total_time_minutes": 30,
            "visit_type": "ESTABLISHED_PATIENT",
        },
    },
    timeout=60,
)
if generate_response.status_code != 201:
    raise RuntimeError(
        f"Generate failed: {generate_response.status_code} {generate_response.text}"
    )
print("session_id:", generate_response.json()["session_id"])
```

```bash cURL expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
curl --request POST \
  --url https://sdp.suki.ai/api/v1/em-codes \
  --header 'sdp_suki_token: <sdp_suki_token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "sections": [
      {
        "loinc": "10164-2",
        "content": {
          "type": "TEXT",
          "text": "Established patient with hypertension. Medication adjusted. Follow-up planned."
        }
      }
    ],
    "patient": {
      "dob": "1952-03-15",
      "sex": "female",
      "patient_type": "ESTABLISHED_PATIENT"
    },
    "encounter": {
      "date_of_service": "2026-01-15",
      "total_time_minutes": 30,
      "visit_type": "ESTABLISHED_PATIENT"
    }
  }'
```

**3. Poll E/M Coding Status**

Poll [Get E/M coding status](https://developer.suki.ai/em-coding-api-reference/em-coding-sessions/status.md) until the session reaches a terminal state (`completed` or `failed`).

If webhooks are enabled for your partner account, you can wait for the standalone E/M notification instead of polling only. On success, `additional_info.session_type` is **`EM_CODES`**. Failure notifications have no `additional_info`, so match their `session_id` against the session IDs you saved. See [E/M Coding asynchronous notifications](https://developer.suki.ai/em-coding-api-reference/asynchronous/webhook.md) and [E/M Coding webhook events](https://developer.suki.ai/documentation/webhook/em-coding/overview.md).

```typescript TypeScript expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
const BASE_URL = "https://sdp.suki.ai";
const sukiToken = "<sdp_suki_token from login>";
const sessionId = "<session_id from generate>";
const sdpProviderId = "";

const headers: Record<string, string> = { sdp_suki_token: sukiToken };
if (sdpProviderId) headers.sdp_provider_id = sdpProviderId;

for (;;) {
  const statusResponse = await fetch(
    `${BASE_URL}/api/v1/em-codes/${sessionId}/status`,
    { headers },
  );
  const statusBody = await statusResponse.json();
  if (!statusResponse.ok) {
    throw new Error(`Status failed: ${statusResponse.status} ${JSON.stringify(statusBody)}`);
  }
  console.log("E/M coding status:", statusBody.status);
  if (statusBody.status === "completed" || statusBody.status === "failed") {
    break;
  }
  await new Promise((r) => setTimeout(r, 3000));
}
```

```python Python expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
import time

import requests

BASE_URL = "https://sdp.suki.ai"
suki_token = "<sdp_suki_token from login>"
session_id = "<session_id from generate>"
sdp_provider_id = ""

headers = {"sdp_suki_token": suki_token}
if sdp_provider_id:
    headers["sdp_provider_id"] = sdp_provider_id

while True:
    status_response = requests.get(
        f"{BASE_URL}/api/v1/em-codes/{session_id}/status",
        headers=headers,
        timeout=60,
    )
    if status_response.status_code != 200:
        raise RuntimeError(
            f"Status failed: {status_response.status_code} {status_response.text}"
        )
    status = status_response.json()["status"]
    print("E/M coding status:", status)
    if status in ("completed", "failed"):
        break
    time.sleep(3)
```

```bash cURL expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
curl --request GET \
  --url https://sdp.suki.ai/api/v1/em-codes/<session_id>/status \
  --header 'sdp_suki_token: <sdp_suki_token>'
```

**4. Retrieve Generated E/M Codes**

When status is `completed`, call [Get E/M codes](https://developer.suki.ai/em-coding-api-reference/em-coding-sessions/get.md) and map `em_codes.values` into your RCM or EHR handoff.

```typescript TypeScript expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
const BASE_URL = "https://sdp.suki.ai";
const sukiToken = "<sdp_suki_token from login>";
const sessionId = "<session_id from generate>";
const sdpProviderId = "";

const headers: Record<string, string> = { sdp_suki_token: sukiToken };
if (sdpProviderId) headers.sdp_provider_id = sdpProviderId;

const codesResponse = await fetch(`${BASE_URL}/api/v1/em-codes/${sessionId}`, {
  headers,
});
const codes = await codesResponse.json();
if (!codesResponse.ok) {
  throw new Error(`Get codes failed: ${codesResponse.status} ${JSON.stringify(codes)}`);
}
console.log(JSON.stringify(codes, null, 2));
```

```python Python expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
import requests

BASE_URL = "https://sdp.suki.ai"
suki_token = "<sdp_suki_token from login>"
session_id = "<session_id from generate>"
sdp_provider_id = ""

headers = {"sdp_suki_token": suki_token}
if sdp_provider_id:
    headers["sdp_provider_id"] = sdp_provider_id

codes_response = requests.get(
    f"{BASE_URL}/api/v1/em-codes/{session_id}",
    headers=headers,
    timeout=60,
)
if codes_response.status_code != 200:
    raise RuntimeError(
        f"Get codes failed: {codes_response.status_code} {codes_response.text}"
    )
print(codes_response.json())
```

```bash cURL expandable theme={"theme":{"light":"one-light","dark":"material-theme-darker"}}
curl --request GET \
  --url https://sdp.suki.ai/api/v1/em-codes/<session_id> \
  --header 'sdp_suki_token: <sdp_suki_token>'
```

> [!NOTE]
>
> For complete technical specifications, refer to the relevant API Reference pages.

## Verify your integration

Before you design the full production workflow, confirm that your integration can complete this minimum path:

* Authenticate successfully and use the returned `sdp_suki_token` in follow-up requests.
* Start a standalone E/M coding session with at least one note section.
* Poll status until the session completes.
* Retrieve generated E/M codes from `GET /api/v1/em-codes/{session_id}`.

After this path works end to end, add richer clinical context, webhook handling, E/M Coding with Ambient when needed, and production error handling.

## Next steps

&#x20;**[E/M Coding overview](https://developer.suki.ai/documentation/concepts/em-coding/overview.md)** - Capability framing, ambient vs standalone, and use cases.

&#x20;**[Add E/M codes to an ambient visit](https://developer.suki.ai/documentation/how-to/em-coding/generate-with-ambient.md)** - Opt in on create session and retrieve ambient E/M codes.

&#x20;**[E/M Coding webhook payload](https://developer.suki.ai/documentation/webhook/em-coding/payload.md)** - Success and failure payload fields for standalone E/M Coding.

&#x20;**[E/M Coding error messages](https://developer.suki.ai/em-coding-api-reference/error-messages-em-coding.md)** - Validation and session errors for the standalone APIs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.