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

# Get Form Filling Session Recording

> Get presigned URLs for Form filling session recordings for streaming or download

Use this endpoint to get presigned URLs for all recordings for a **Form filling** session.

Pass the Form filling `ambient_session_id` from [Create Form Filling session](/form-filling-api-reference/form-filling-sessions/create) in the path.

<Note>
  Use the `ambient_session_id` from [Create Form Filling session](/form-filling-api-reference/form-filling-sessions/create). It is not the same value as an [Create Ambient session](/api-reference/ambient-sessions/create), even though both fields use the name `ambient_session_id`.
</Note>

For how to use presigned URLs after retrieval, refer to [Ambient audio streaming & download](/documentation/audio-streaming-download).

Use the `download` query parameter to control the URL type:

* If `download=true`, the URL is for downloading the **full** file
* If `download=false` or omitted, the URL supports streaming with **range** requests

## Code examples

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    import requests

    # Form filling ambient_session_id from POST /api/v1/form-filling/session/create
    form_filling_session_id = "123dfg-456dfg-789dfg-012dfg"
    url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{form_filling_session_id}/recording"

    headers = {
        "sdp_suki_token": "<sdp_suki_token>",
        "sdp_provider_id": "<sdp_provider_id>",
    }

    # For streaming URLs (default)
    response = requests.get(url, headers=headers)

    # For download-only URLs
    # response = requests.get(url, headers=headers, params={"download": True})

    if response.status_code == 200:
        data = response.json()
        print(f"Streamable: {data.get('is_streamable')}")
        for rec in data.get("recordings", []):
            print(f"Recording ID: {rec.get('recording_id')}")
            print(f"Presigned URL: {rec.get('presigned_url')}")
            print(f"Expires at: {rec.get('expires_at')}")
            print(f"Sequence: {rec.get('sequence_number')}")
            print("---")
    else:
        print(f"Failed to get recording URLs: {response.status_code}")
        print(response.json())
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    // Form filling ambient_session_id from POST /api/v1/form-filling/session/create
    const formFillingSessionId = '123dfg-456dfg-789dfg-012dfg';

    const response = await fetch(
      `https://sdp.suki-stage.com/api/v1/ambient/session/${formFillingSessionId}/recording`,
      {
        headers: {
          sdp_suki_token: '<sdp_suki_token>',
          sdp_provider_id: '<sdp_provider_id>',
        },
      },
    );

    // For download-only URLs, append ?download=true

    if (response.ok) {
      const data = await response.json();
      console.log('Streamable:', data.is_streamable);
      data.recordings?.forEach((rec: {
        recording_id?: string;
        presigned_url?: string;
        expires_at?: number;
        sequence_number?: number;
      }) => {
        console.log('Recording ID:', rec.recording_id);
        console.log('Presigned URL:', rec.presigned_url);
        console.log('Expires at:', rec.expires_at);
        console.log('Sequence:', rec.sequence_number);
        console.log('---');
      });
    } else {
      const error = await response.json();
      console.error(`Failed to get recording URLs: ${response.status}`, error);
    }
    ```
  </Tab>
</Tabs>


## OpenAPI

````yaml GET /api/v1/ambient/session/{ambient_session_id}/recording
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/ambient/session/{ambient_session_id}/recording:
    get:
      tags:
        - /api/v1/ambient/session
      summary: Get ambient session recording URLs
      description: >-
        Returns presigned URLs to stream or download session recordings. URLs
        are temporary; use them before they expire.
      operationId: getSessionRecording
      parameters:
        - name: ambient_session_id
          in: path
          description: >-
            UUID for the ambient session. Use the `ambient_session_id` returned
            from Create Ambient Session, or the UUID you supplied in that
            request.
          required: true
          schema:
            type: string
        - name: download
          in: query
          description: >-
            If true, returns download-only URLs; if false or omitted, URLs
            support streaming with Range requests.
          required: false
          schema:
            type: boolean
        - $ref: '#/components/parameters/ProviderIdHeader'
      responses:
        '200':
          description: Request succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.SessionRecordingResponse'
              example:
                recordings:
                  - recording_id: 01KFJZTJWZH28GRHQXVCGW4Y47
                    presigned_url: https://storage.googleapis.com/...
                    expires_at: 1738765432
                    sequence_number: 1
                is_streamable: true
        '400':
          description: Bad request. The request body or parameters failed validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.BadRequestError'
        '401':
          description: >-
            Expired or missing token. User message returned in the response
            body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.AuthenticationError'
              example:
                code: 401
                message: Invalid authentication credentials.
        '404':
          description: >-
            Session exists, but recording audio is missing or not yet available.
            User message returned in the response body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.NotFoundError'
              example:
                code: 404
                message: Recording not found or decryption in progress.
        '410':
          description: >-
            Session is past the recording retention period (7 days). User
            message returned in the response body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.NotFoundError'
              example:
                code: 410
                message: Recording has expired per retention policy.
        '500':
          description: Service failure. User message returned in the response body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/controllers.InternalServerError'
              example:
                code: 500
                message: An internal error occurred.
      security:
        - SukiTokenAuth: []
      x-codeSamples:
        - lang: bash
          label: cURL
          source: |-
            curl --request GET \
              --url https://sdp.suki.ai/api/v1/ambient/session/<ambient_session_id>/recording?download=<download> \
              --header 'sdp_suki_token: <sdp_suki_token>' \
              --header 'sdp_provider_id: <sdp_provider_id>'
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.SessionRecordingResponse:
      type: object
      properties:
        recordings:
          type: array
          description: List of recordings with presigned URLs for the ambient session.
          items:
            $ref: '#/components/schemas/controllers.RecordingItem'
        is_streamable:
          type: boolean
          description: Whether the returned URLs support streaming with Range requests.
          example: true
      description: Response body for the /session/{ambient_session_id}/recording endpoint
    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.NotFoundError:
      type: object
      properties:
        code:
          type: integer
          example: 404
          description: HTTP status code for the error.
        message:
          type: string
          example: not found
          description: Human-readable description of the missing resource.
      description: Error response when the requested resource was not found.
    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.
    controllers.RecordingItem:
      type: object
      properties:
        recording_id:
          type: string
          description: Unique identifier for the recording.
          example: 01KFJZTJWZH28GRHQXVCGW4Y47
        presigned_url:
          type: string
          description: Temporary URL to stream or download the recording.
          example: https://storage.googleapis.com/...
        expires_at:
          type: integer
          description: Unix timestamp when the presigned URL expires.
          example: 1738765432
        sequence_number:
          type: integer
          description: Order or part index of the recording.
          example: 1
      description: A single recording entry with presigned URL and metadata
  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.

````