> ## 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.

# Create Form Filling Session

> Create a Form filling session and obtain a session identifier for subsequent calls

Use this endpoint to create a Form filling session. Suki returns a Form filling `ambient_session_id`. Use that value for context, streaming, end, status, structured data, feedback, and related session operations.
You can create a Form filling session with an empty request body. Suki generates `ambient_session_id` for you.

Add a field when you need the behavior it enables:

* **`ambient_session_id`**: Supply your own Form filling session ID (Must be a valid UUID). If you omit it, Suki generates one and returns it.
* **`correlation_id`**: Supply a client value for tracing or correlating the session in your own systems.

All fields are **optional** when creating a standalone Form filling session.

<Note>
  Both Form filling and the Ambient APIs use the field name `ambient_session_id`, but the values identify different sessions. Do not pass an [Ambient API](/api-reference/ambient-sessions/create) session ID here. Use only the Form filling `ambient_session_id` returned from this endpoint for Form filling REST calls and for `/ws/stream`.
</Note>

## Code examples

<Note>
  The code examples below use placeholders and the stage host `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](/api-reference/api-guidelines#using-code-examples-in-your-integration) in the **API Reference Guidelines**.
</Note>

**Language tabs (agents):** Equivalent code samples are available in: Python, TypeScript. Humans see one language at a time. Use the variant that matches the user's stack; behavior is the same across tabs.

<Tabs>
  <Tab title="Python">
    ```python expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    from typing import Any, Optional, TypedDict, cast

    import requests

    BASE_URL = "https://sdp.suki-stage.com"


    class CreateFormFillingSessionRequest(TypedDict, total=False):
        ambient_session_id: str
        correlation_id: str


    class CreateFormFillingSessionResponse(TypedDict):
        ambient_session_id: str


    class ApiHttpError(RuntimeError):
        """Wrong HTTP status; OpenAPI errors usually include JSON with message + code."""

        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) -> dict[str, Any]:
        r = requests.post(url, json=payload, headers=headers, timeout=60)
        if r.status_code == expect_status:
            data = r.json()
            if isinstance(data, dict):
                return data
            raise ApiHttpError(expect_status, url, "response JSON was not an object")

        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:
        """POST /api/v1/auth/login -> suki_token (HTTP 200)."""
        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
        data = _post_json_expect(url, {"Content-Type": "application/json"}, body, 200)
        token = data.get("suki_token")
        if not isinstance(token, str) or not token:
            raise ValueError(f"{url}: 200 response missing suki_token")
        return token


    def create_form_filling_session(
        suki_token: str,
        body: Optional[CreateFormFillingSessionRequest] = None,
    ) -> CreateFormFillingSessionResponse:
        """POST /api/v1/form-filling/session/create (sdp_suki_token header required). HTTP 201."""
        url = f"{BASE_URL}/api/v1/form-filling/session/create"
        headers = {"sdp_suki_token": suki_token, "sdp_provider_id": "<sdp_provider_id>", "Content-Type": "application/json"}
        data = _post_json_expect(url, headers, dict(body or {}), 201)
        sid = data.get("ambient_session_id")
        if not isinstance(sid, str) or not sid:
            raise ValueError(f"{url}: 201 response missing ambient_session_id")
        return cast(CreateFormFillingSessionResponse, {"ambient_session_id": sid})


    if __name__ == "__main__":
        try:
            token = login_for_suki_token("<partner_id>", "<partner_token>")
            session = create_form_filling_session(token, {})
            print(session["ambient_session_id"])
        except (ApiHttpError, ValueError) as e:
            print(e)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    const BASE_URL = "https://sdp.suki-stage.com";

    type AuthenticationRequest = {
      partner_id: string;
      partner_token: string;
      provider_id?: string;
    };

    type AuthenticationResponse = { suki_token: string };

    type CreateFormFillingSessionRequest = {
      ambient_session_id?: string;
      correlation_id?: string;
    };

    type CreateFormFillingSessionResponse = { ambient_session_id: string };

    /** POST helper: reads body once, checks status, returns parsed JSON object on success. */
    async function postJsonExpect<T extends Record<string, unknown>>(
      url: string,
      init: RequestInit,
      expectStatus: number,
    ): Promise<T> {
      const res = await fetch(url, init);
      const text = await res.text();
      let data: unknown;
      try {
        data = text ? JSON.parse(text) : {};
      } catch {
        throw new Error(`HTTP ${res.status} ${url}: invalid JSON`);
      }
      if (res.status !== expectStatus) {
        const msg =
          data && typeof data === "object" && "message" in data
            ? String((data as { message?: string }).message)
            : text.slice(0, 500);
        throw new Error(`HTTP ${res.status} ${url}: ${msg || "(no body)"}`);
      }
      if (!data || typeof data !== "object") {
        throw new Error(`${url}: expected JSON object`);
      }
      return data as T;
    }

    async function loginForSukiToken(body: AuthenticationRequest): Promise<string> {
      const url = `${BASE_URL}/api/v1/auth/login`;
      const data = await postJsonExpect<AuthenticationResponse>(url, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      }, 200);
      if (!data.suki_token) throw new Error(`${url}: missing suki_token`);
      return data.suki_token;
    }

    async function createFormFillingSession(
      sukiToken: string,
      body: CreateFormFillingSessionRequest = {},
    ): Promise<CreateFormFillingSessionResponse> {
      const url = `${BASE_URL}/api/v1/form-filling/session/create`;
      const data = await postJsonExpect<CreateFormFillingSessionResponse>(url, {
        method: "POST",
        headers: {
          sdp_suki_token: sukiToken, sdp_provider_id: "<sdp_provider_id>",
          "Content-Type": "application/json",
        },
        body: JSON.stringify(body),
      }, 201);
      if (!data.ambient_session_id) throw new Error(`${url}: missing ambient_session_id`);
      return data;
    }

    async function main(): Promise<void> {
      try {
        const token = await loginForSukiToken({
          partner_id: "<partner_id>",
          partner_token: "<partner_token>",
        });
        const session = await createFormFillingSession(token, {});
        console.log(session.ambient_session_id);
      } catch (e) {
        console.error(e instanceof Error ? e.message : e);
      }
    }

    void main();
    ```
  </Tab>
</Tabs>


## OpenAPI

````yaml POST /api/v1/form-filling/session/create
openapi: 3.0.1
info:
  title: Suki Developer Platform
  description: >-
    REST and WebSocket APIs for the Suki Developer Platform. Authenticate with
    Login or Register to obtain a Suki access token, then integrate ambient
    clinical documentation, form filling, transcription, and reference metadata
    endpoints.
  contact: {}
  version: '1.0'
servers:
  - url: https://sdp.suki.ai
    description: >-
      Production base URL for Suki Developer Platform REST APIs. WebSocket
      endpoints use the same host with `wss://`.
security:
  - SukiTokenAuth: []
paths:
  /api/v1/form-filling/session/create:
    post:
      tags:
        - /api/v1/form-filling/session
      summary: Create form-filling session
      description: >-
        Creates a form-filling session for structured medical form capture.
        Returns a session ID in the `ambient_session_id` response field. That ID
        identifies the form-filling session for context, streaming, status,
        structured-data, and feedback APIs. It is not an ambient clinical
        documentation session ID.
      parameters:
        - $ref: '#/components/parameters/ProviderIdHeader'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/controllers.CreateFormFillingSessionRequest'
            example: {}
      responses:
        '201':
          description: Resource created successfully.
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/controllers.CreateFormFillingSessionResponse
        '400':
          description: Bad request. The request body or parameters failed validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.BadRequestError'
        '401':
          description: Unauthorized. The Suki access token is missing, expired, or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.AuthenticationError'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.InternalServerError'
      security:
        - SukiTokenAuth: []
      x-codeSamples:
        - lang: bash
          label: cURL
          source: |-
            curl --request POST \
              --url https://sdp.suki.ai/api/v1/form-filling/session/create \
              --header 'Content-Type: application/json' \
              --header 'sdp_suki_token: <sdp_suki_token>' \
              --header 'sdp_provider_id: <sdp_provider_id>' \
              --data '{}'
components:
  parameters:
    ProviderIdHeader:
      name: sdp_provider_id
      in: header
      description: >-
        **Optional** for standard partners.


        **Required** for:


        - **Bearer authentication.** Use the same `provider_id` returned by the
        Login or Register API.

        - **Single Auth Token authentication.** Include the same `provider_id`
        on every request as `sdp_provider_id`.
      required: false
      schema:
        type: string
        example: provider-123
  schemas:
    controllers.CreateFormFillingSessionRequest:
      description: >-
        Optional form-filling session ID and correlation metadata. Suki
        generates a form-filling session ID when omitted.
      type: object
      properties:
        ambient_session_id:
          type: string
          description: >-
            **Optional** - Form-filling session ID in UUID format. Suki
            generates one when omitted and returns it in the
            `ambient_session_id` response field. Do not pass an ambient clinical
            documentation session ID.
          example: 123dfg-456dfg-789dfg-012dfg
        correlation_id:
          type: string
          description: >-
            **Optional** - Client-supplied identifier for tracing or correlating
            requests.
          example: 123dfg-456dfg-789dfg-012dfg
    controllers.CreateFormFillingSessionResponse:
      description: New form-filling session ID returned after create.
      type: object
      properties:
        ambient_session_id:
          type: string
          description: >-
            Form-filling session ID for subsequent form-filling API calls.
            Despite the field name, this is not an ambient clinical
            documentation session ID.
          example: 123dfg-456dfg-789dfg-012dfg
    controllers.BadRequestError:
      description: Bad Request Response
      type: object
      properties:
        code:
          type: integer
          example: 400
        message:
          type: string
          example: invalid request
    controllers.AuthenticationError:
      description: Authentication Failure Response
      type: object
      properties:
        code:
          type: integer
          example: 401
        message:
          type: string
          example: invalid token
    controllers.InternalServerError:
      description: Internal Server Error Response
      type: object
      properties:
        code:
          type: integer
          example: 500
        message:
          type: string
          example: internal server error
  securitySchemes:
    SukiTokenAuth:
      type: apiKey
      in: header
      name: sdp_suki_token
      description: >-
        Suki access token (`suki_token`) from Login or Register. Expires after
        one hour.

````