> ## 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 an ambient session identifier for subsequent calls

Use this endpoint to create a Form filling ambient session. Suki will return a Form filling ambient session identifier (id) in response for subsequent calls.

You must use the returned session identifier (id) to perform other operations for that session for example checking session status, retrieving structured data, submitting feedback, ending the session, and more.

<Note>
  **Important**:

  In the documentation, both the Form filling session ID and the [Suki Ambient API session ID](/api-reference/ambient-sessions/create) are referred to as `ambient_session_id`. However, these are two different identifiers and should not be treated as the same value.
</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>

<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** - Stable identifier for the active provider. Omit for
        standard partners whose `partner_token` identifies the user.
        **Required** for Bearer partners and Single Auth Token authentication
        where multiple providers share one `partner_token`. Use the same
        `provider_id` you sent on Login or Register.
      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:
      type: object
      properties:
        code:
          type: integer
          example: 400
          description: HTTP status code for the error.
        message:
          type: string
          example: invalid request
          description: Human-readable description of the validation or request error.
      description: Error response when the request fails validation.
    controllers.AuthenticationError:
      type: object
      properties:
        code:
          type: integer
          example: 401
          description: HTTP status code for the error.
        message:
          type: string
          example: invalid token
          description: Human-readable description of the authentication failure.
      description: Error response when authentication fails.
    controllers.InternalServerError:
      type: object
      properties:
        code:
          type: integer
          example: 500
          description: HTTP status code for the error.
        message:
          type: string
          example: internal server error
          description: Human-readable description of the server error.
      description: Error response when the server encounters an unexpected error.
  securitySchemes:
    SukiTokenAuth:
      type: apiKey
      in: header
      name: sdp_suki_token
      description: >-
        Suki access token for the authenticated provider. Obtain this by calling
        Login or Register with a valid `partner_token`. Pass the `suki_token`
        value from the JSON response as the `sdp_suki_token` header on REST
        requests and non-browser WebSocket upgrades. Browser WebSocket clients
        pass the token in `Sec-WebSocket-Protocol` instead. Tokens expire after
        one hour; call Login again to refresh.

````