# This file was auto-generated by Fern from our API Definition.

import typing
import uuid
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from .errors.authentication_error import AuthenticationError
from .errors.batch_not_found import BatchNotFound
from .errors.rate_limit_error import RateLimitError
from .errors.transcription_not_found import TranscriptionNotFound
from .types.batch_audio_source import BatchAudioSource
from .types.batch_file_content_type import BatchFileContentType
from .types.batch_file_detail import BatchFileDetail
from .types.batch_file_metadata import BatchFileMetadata
from .types.batch_file_upload_response import BatchFileUploadResponse
from .types.batch_status_response import BatchStatusResponse
from .types.batch_transcription_response import BatchTranscriptionResponse
from .types.list_batch_files_response import ListBatchFilesResponse
from .types.processing_mode import ProcessingMode
from .types.transcription import Transcription
from .types.transcription_id import TranscriptionId
from .types.transcription_info import TranscriptionInfo
from .types.transcription_request_info import TranscriptionRequestInfo
from .types.transcription_summary import TranscriptionSummary

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawTranscribeClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def create_transcription(
        self,
        *,
        info: TranscriptionRequestInfo,
        audio_url: typing.Optional[str] = OMIT,
        audio_file: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[TranscriptionId]:
        """
        Create a new transcription

        Parameters
        ----------
        info : TranscriptionRequestInfo
            Transcription parameters

        audio_url : typing.Optional[str]
            URL to a downloadable audio file. Must be a direct link to the file (not a streaming or preview link). If the URL is not directly downloadable, consider using our Link API to extract a downloadable link from supported sites. Either audio_url or audio_file must be provided, but not both.

        audio_file : typing.Optional[str]
            Base64 encoded audio file content. Either audio_url or audio_file must be provided, but not both.

            ## Base64 Encoding Example

            **Python:**
            ```python
            import base64
            from soferai import SoferAI

            # Initialize client
            client = SoferAI(api_key="your_api_key_here")

            # Read and encode audio file
            with open("audio.mp3", "rb") as f:
                base64_audio = base64.b64encode(f.read()).decode("utf-8")

            # Create transcription request
            response = client.transcribe.create_transcription(
                audio_file=base64_audio,
                info={
                    "model": "v1",
                    "primary_language": "en",
                    "hebrew_word_format": ["he"],
                    "title": "My Shiur Transcription",
                },
            )

            print(f"Transcription ID: {response}")
            ```

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[TranscriptionId]
            The unique identifier for the newly created transcription.
            Use this ID to check the status of the transcription or to retrieve the transcription result.
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/transcriptions/",
            method="POST",
            json={
                "audio_url": audio_url,
                "audio_file": audio_file,
                "info": convert_and_respect_annotation_metadata(
                    object_=info, annotation=TranscriptionRequestInfo, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TranscriptionId,
                    parse_obj_as(
                        type_=TranscriptionId,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_batch_transcription(
        self,
        *,
        info: TranscriptionRequestInfo,
        processing_mode: typing.Optional[ProcessingMode] = OMIT,
        batch_file_id: typing.Optional[uuid.UUID] = OMIT,
        audio_sources: typing.Optional[typing.Sequence[BatchAudioSource]] = OMIT,
        batch_title: typing.Optional[str] = OMIT,
        batch_id: typing.Optional[uuid.UUID] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[BatchTranscriptionResponse]:
        """
        Create multiple transcriptions in a single batch request.

        **Choose a processing mode:**

        - **Express mode**: Transcriptions start immediately. Max 10 files. Higher cost. Pass `audio_sources` directly in the request.
        - **Standard mode**: Transcriptions processed within 24 hours. Max 500 files. Lower cost. First upload a manifest via [Upload Batch File](/api-reference/transcribe/upload-batch-file), then pass the `batch_file_id` here.

        All files in the batch share the same transcription settings (model, language, etc.) defined in `info`.

        Parameters
        ----------
        info : TranscriptionRequestInfo
            Transcription settings applied to all files in the batch (model, language, etc.)

        processing_mode : typing.Optional[ProcessingMode]
            Choose how the batch is processed:
            - `standard` (default): Lower cost, processed within 24 hours. Max 500 files. Use with `batch_file_id`.
            - `express`: Higher cost, starts immediately. Max 10 files. Use with `audio_sources`.

        batch_file_id : typing.Optional[uuid.UUID]
            **For standard mode only.** ID of a previously uploaded batch manifest.

            Get this by calling [Upload Batch File](/api-reference/transcribe/upload-batch-file) first.

        audio_sources : typing.Optional[typing.Sequence[BatchAudioSource]]
            **For express mode only.** List of audio URLs to transcribe (max 10).

            Each item needs an `audio_url` and can optionally include a `title`.

        batch_title : typing.Optional[str]
            Default title prefix for transcriptions. Individual items can override this. Items without titles become "{batch_title} - Item 1", "{batch_title} - Item 2", etc.

        batch_id : typing.Optional[uuid.UUID]
            Custom UUID for this batch. Auto-generated if not provided.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[BatchTranscriptionResponse]
            Returns the batch ID and individual transcription IDs. Use [Get Batch Status](/api-reference/transcribe/get-batch-status) to track progress.
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/transcriptions/batch",
            method="POST",
            json={
                "processing_mode": processing_mode,
                "batch_file_id": batch_file_id,
                "audio_sources": convert_and_respect_annotation_metadata(
                    object_=audio_sources, annotation=typing.Sequence[BatchAudioSource], direction="write"
                ),
                "info": convert_and_respect_annotation_metadata(
                    object_=info, annotation=TranscriptionRequestInfo, direction="write"
                ),
                "batch_title": batch_title,
                "batch_id": batch_id,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchTranscriptionResponse,
                    parse_obj_as(
                        type_=BatchTranscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def upload_batch_file(
        self,
        *,
        content_type: BatchFileContentType,
        json_items: typing.Optional[typing.Sequence[BatchAudioSource]] = OMIT,
        jsonl: typing.Optional[str] = OMIT,
        metadata: typing.Optional[BatchFileMetadata] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[BatchFileUploadResponse]:
        """
        Upload a batch manifest containing audio URLs for standard mode batch processing.

        **Workflow:**
        1. Upload your manifest here to get a `batch_file_id`
        2. Use that ID in [Create Batch Transcription](/api-reference/transcribe/create-batch-transcription) with `processing_mode: "standard"`

        The manifest is a list of audio sources (max 500), each with a URL and optional title. You can provide it as a JSON array or JSONL format.

        Parameters
        ----------
        content_type : BatchFileContentType
            Format of your manifest data

        json_items : typing.Optional[typing.Sequence[BatchAudioSource]]
            **For JSON format.** Array of audio sources to transcribe (max 500).

        jsonl : typing.Optional[str]
            **For JSONL format.** One audio source per line as JSON, separated by newlines (max 500 lines).

            Example: `{"audio_url": "https://..."}\n{"audio_url": "https://..."}`

        metadata : typing.Optional[BatchFileMetadata]
            Optional title and description for this manifest

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[BatchFileUploadResponse]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/transcriptions/batch-files",
            method="POST",
            json={
                "content_type": content_type,
                "json_items": convert_and_respect_annotation_metadata(
                    object_=json_items, annotation=typing.Sequence[BatchAudioSource], direction="write"
                ),
                "jsonl": jsonl,
                "metadata": convert_and_respect_annotation_metadata(
                    object_=metadata, annotation=BatchFileMetadata, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchFileUploadResponse,
                    parse_obj_as(
                        type_=BatchFileUploadResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list_batch_files(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[ListBatchFilesResponse]:
        """
        List all batch file manifests you've uploaded. Use this to find a `batch_file_id` for starting a standard mode batch.

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[ListBatchFilesResponse]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/transcriptions/batch-files",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ListBatchFilesResponse,
                    parse_obj_as(
                        type_=ListBatchFilesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_batch_file(
        self, batch_file_id: uuid.UUID, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[BatchFileDetail]:
        """
        Get details about a specific batch file manifest, including its validation status. Check this after uploading to ensure your manifest is valid before starting a batch.

        Parameters
        ----------
        batch_file_id : uuid.UUID
            The batch file ID returned from [Upload Batch File](/api-reference/transcribe/upload-batch-file)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[BatchFileDetail]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/transcriptions/batch-files/{jsonable_encoder(batch_file_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchFileDetail,
                    parse_obj_as(
                        type_=BatchFileDetail,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise BatchNotFound(headers=dict(_response.headers))
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_batch_status(
        self, batch_id: uuid.UUID, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[BatchStatusResponse]:
        """
        Check the progress of a batch transcription. Returns counts of completed, failed, and pending transcriptions, plus details for each individual transcription.

        Parameters
        ----------
        batch_id : uuid.UUID
            The batch ID returned from [Create Batch Transcription](/api-reference/transcribe/create-batch-transcription)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[BatchStatusResponse]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/transcriptions/batch/{jsonable_encoder(batch_id)}/status",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchStatusResponse,
                    parse_obj_as(
                        type_=BatchStatusResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise BatchNotFound(headers=dict(_response.headers))
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_transcription_status(
        self, transcription_id: uuid.UUID, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[TranscriptionInfo]:
        """
        Get transcription status

        Parameters
        ----------
        transcription_id : uuid.UUID
            ID of the transcription. Use the ID returned from the Create Transcription endpoint.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[TranscriptionInfo]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/transcriptions/{jsonable_encoder(transcription_id)}/status",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TranscriptionInfo,
                    parse_obj_as(
                        type_=TranscriptionInfo,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise TranscriptionNotFound(headers=dict(_response.headers))
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_transcription(
        self,
        transcription_id: uuid.UUID,
        *,
        filter_hebrew_word_format: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Transcription]:
        """
        Get transcription

        Parameters
        ----------
        transcription_id : uuid.UUID
            ID of the transcription. Use the ID returned from the Create Transcription endpoint.

        filter_hebrew_word_format : typing.Optional[str]
            Optionally filter the response to a single Hebrew word format. If set to 'en', the response text will have Hebrew characters removed and timestamps will exclude words tagged with 'he'. If set to 'he', italicized transliterations are removed from the text and timestamps will exclude words tagged only with 'en'. If set to 'hybrid', the response includes both transliteration and Hebrew characters for each word.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[Transcription]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/transcriptions/{jsonable_encoder(transcription_id)}",
            method="GET",
            params={
                "filter_hebrew_word_format": filter_hebrew_word_format,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Transcription,
                    parse_obj_as(
                        type_=Transcription,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise TranscriptionNotFound(headers=dict(_response.headers))
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list_transcriptions(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[typing.List[TranscriptionSummary]]:
        """
        Get all transcriptions for the authenticated user

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[typing.List[TranscriptionSummary]]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/transcriptions/",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[TranscriptionSummary],
                    parse_obj_as(
                        type_=typing.List[TranscriptionSummary],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


class AsyncRawTranscribeClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def create_transcription(
        self,
        *,
        info: TranscriptionRequestInfo,
        audio_url: typing.Optional[str] = OMIT,
        audio_file: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[TranscriptionId]:
        """
        Create a new transcription

        Parameters
        ----------
        info : TranscriptionRequestInfo
            Transcription parameters

        audio_url : typing.Optional[str]
            URL to a downloadable audio file. Must be a direct link to the file (not a streaming or preview link). If the URL is not directly downloadable, consider using our Link API to extract a downloadable link from supported sites. Either audio_url or audio_file must be provided, but not both.

        audio_file : typing.Optional[str]
            Base64 encoded audio file content. Either audio_url or audio_file must be provided, but not both.

            ## Base64 Encoding Example

            **Python:**
            ```python
            import base64
            from soferai import SoferAI

            # Initialize client
            client = SoferAI(api_key="your_api_key_here")

            # Read and encode audio file
            with open("audio.mp3", "rb") as f:
                base64_audio = base64.b64encode(f.read()).decode("utf-8")

            # Create transcription request
            response = client.transcribe.create_transcription(
                audio_file=base64_audio,
                info={
                    "model": "v1",
                    "primary_language": "en",
                    "hebrew_word_format": ["he"],
                    "title": "My Shiur Transcription",
                },
            )

            print(f"Transcription ID: {response}")
            ```

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[TranscriptionId]
            The unique identifier for the newly created transcription.
            Use this ID to check the status of the transcription or to retrieve the transcription result.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/transcriptions/",
            method="POST",
            json={
                "audio_url": audio_url,
                "audio_file": audio_file,
                "info": convert_and_respect_annotation_metadata(
                    object_=info, annotation=TranscriptionRequestInfo, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TranscriptionId,
                    parse_obj_as(
                        type_=TranscriptionId,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_batch_transcription(
        self,
        *,
        info: TranscriptionRequestInfo,
        processing_mode: typing.Optional[ProcessingMode] = OMIT,
        batch_file_id: typing.Optional[uuid.UUID] = OMIT,
        audio_sources: typing.Optional[typing.Sequence[BatchAudioSource]] = OMIT,
        batch_title: typing.Optional[str] = OMIT,
        batch_id: typing.Optional[uuid.UUID] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[BatchTranscriptionResponse]:
        """
        Create multiple transcriptions in a single batch request.

        **Choose a processing mode:**

        - **Express mode**: Transcriptions start immediately. Max 10 files. Higher cost. Pass `audio_sources` directly in the request.
        - **Standard mode**: Transcriptions processed within 24 hours. Max 500 files. Lower cost. First upload a manifest via [Upload Batch File](/api-reference/transcribe/upload-batch-file), then pass the `batch_file_id` here.

        All files in the batch share the same transcription settings (model, language, etc.) defined in `info`.

        Parameters
        ----------
        info : TranscriptionRequestInfo
            Transcription settings applied to all files in the batch (model, language, etc.)

        processing_mode : typing.Optional[ProcessingMode]
            Choose how the batch is processed:
            - `standard` (default): Lower cost, processed within 24 hours. Max 500 files. Use with `batch_file_id`.
            - `express`: Higher cost, starts immediately. Max 10 files. Use with `audio_sources`.

        batch_file_id : typing.Optional[uuid.UUID]
            **For standard mode only.** ID of a previously uploaded batch manifest.

            Get this by calling [Upload Batch File](/api-reference/transcribe/upload-batch-file) first.

        audio_sources : typing.Optional[typing.Sequence[BatchAudioSource]]
            **For express mode only.** List of audio URLs to transcribe (max 10).

            Each item needs an `audio_url` and can optionally include a `title`.

        batch_title : typing.Optional[str]
            Default title prefix for transcriptions. Individual items can override this. Items without titles become "{batch_title} - Item 1", "{batch_title} - Item 2", etc.

        batch_id : typing.Optional[uuid.UUID]
            Custom UUID for this batch. Auto-generated if not provided.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[BatchTranscriptionResponse]
            Returns the batch ID and individual transcription IDs. Use [Get Batch Status](/api-reference/transcribe/get-batch-status) to track progress.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/transcriptions/batch",
            method="POST",
            json={
                "processing_mode": processing_mode,
                "batch_file_id": batch_file_id,
                "audio_sources": convert_and_respect_annotation_metadata(
                    object_=audio_sources, annotation=typing.Sequence[BatchAudioSource], direction="write"
                ),
                "info": convert_and_respect_annotation_metadata(
                    object_=info, annotation=TranscriptionRequestInfo, direction="write"
                ),
                "batch_title": batch_title,
                "batch_id": batch_id,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchTranscriptionResponse,
                    parse_obj_as(
                        type_=BatchTranscriptionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def upload_batch_file(
        self,
        *,
        content_type: BatchFileContentType,
        json_items: typing.Optional[typing.Sequence[BatchAudioSource]] = OMIT,
        jsonl: typing.Optional[str] = OMIT,
        metadata: typing.Optional[BatchFileMetadata] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[BatchFileUploadResponse]:
        """
        Upload a batch manifest containing audio URLs for standard mode batch processing.

        **Workflow:**
        1. Upload your manifest here to get a `batch_file_id`
        2. Use that ID in [Create Batch Transcription](/api-reference/transcribe/create-batch-transcription) with `processing_mode: "standard"`

        The manifest is a list of audio sources (max 500), each with a URL and optional title. You can provide it as a JSON array or JSONL format.

        Parameters
        ----------
        content_type : BatchFileContentType
            Format of your manifest data

        json_items : typing.Optional[typing.Sequence[BatchAudioSource]]
            **For JSON format.** Array of audio sources to transcribe (max 500).

        jsonl : typing.Optional[str]
            **For JSONL format.** One audio source per line as JSON, separated by newlines (max 500 lines).

            Example: `{"audio_url": "https://..."}\n{"audio_url": "https://..."}`

        metadata : typing.Optional[BatchFileMetadata]
            Optional title and description for this manifest

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[BatchFileUploadResponse]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/transcriptions/batch-files",
            method="POST",
            json={
                "content_type": content_type,
                "json_items": convert_and_respect_annotation_metadata(
                    object_=json_items, annotation=typing.Sequence[BatchAudioSource], direction="write"
                ),
                "jsonl": jsonl,
                "metadata": convert_and_respect_annotation_metadata(
                    object_=metadata, annotation=BatchFileMetadata, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchFileUploadResponse,
                    parse_obj_as(
                        type_=BatchFileUploadResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list_batch_files(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[ListBatchFilesResponse]:
        """
        List all batch file manifests you've uploaded. Use this to find a `batch_file_id` for starting a standard mode batch.

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[ListBatchFilesResponse]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/transcriptions/batch-files",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ListBatchFilesResponse,
                    parse_obj_as(
                        type_=ListBatchFilesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_batch_file(
        self, batch_file_id: uuid.UUID, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[BatchFileDetail]:
        """
        Get details about a specific batch file manifest, including its validation status. Check this after uploading to ensure your manifest is valid before starting a batch.

        Parameters
        ----------
        batch_file_id : uuid.UUID
            The batch file ID returned from [Upload Batch File](/api-reference/transcribe/upload-batch-file)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[BatchFileDetail]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/transcriptions/batch-files/{jsonable_encoder(batch_file_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchFileDetail,
                    parse_obj_as(
                        type_=BatchFileDetail,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise BatchNotFound(headers=dict(_response.headers))
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_batch_status(
        self, batch_id: uuid.UUID, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[BatchStatusResponse]:
        """
        Check the progress of a batch transcription. Returns counts of completed, failed, and pending transcriptions, plus details for each individual transcription.

        Parameters
        ----------
        batch_id : uuid.UUID
            The batch ID returned from [Create Batch Transcription](/api-reference/transcribe/create-batch-transcription)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[BatchStatusResponse]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/transcriptions/batch/{jsonable_encoder(batch_id)}/status",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchStatusResponse,
                    parse_obj_as(
                        type_=BatchStatusResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise BatchNotFound(headers=dict(_response.headers))
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_transcription_status(
        self, transcription_id: uuid.UUID, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[TranscriptionInfo]:
        """
        Get transcription status

        Parameters
        ----------
        transcription_id : uuid.UUID
            ID of the transcription. Use the ID returned from the Create Transcription endpoint.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[TranscriptionInfo]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/transcriptions/{jsonable_encoder(transcription_id)}/status",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TranscriptionInfo,
                    parse_obj_as(
                        type_=TranscriptionInfo,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise TranscriptionNotFound(headers=dict(_response.headers))
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_transcription(
        self,
        transcription_id: uuid.UUID,
        *,
        filter_hebrew_word_format: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Transcription]:
        """
        Get transcription

        Parameters
        ----------
        transcription_id : uuid.UUID
            ID of the transcription. Use the ID returned from the Create Transcription endpoint.

        filter_hebrew_word_format : typing.Optional[str]
            Optionally filter the response to a single Hebrew word format. If set to 'en', the response text will have Hebrew characters removed and timestamps will exclude words tagged with 'he'. If set to 'he', italicized transliterations are removed from the text and timestamps will exclude words tagged only with 'en'. If set to 'hybrid', the response includes both transliteration and Hebrew characters for each word.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[Transcription]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/transcriptions/{jsonable_encoder(transcription_id)}",
            method="GET",
            params={
                "filter_hebrew_word_format": filter_hebrew_word_format,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Transcription,
                    parse_obj_as(
                        type_=Transcription,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise TranscriptionNotFound(headers=dict(_response.headers))
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list_transcriptions(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[typing.List[TranscriptionSummary]]:
        """
        Get all transcriptions for the authenticated user

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[typing.List[TranscriptionSummary]]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/transcriptions/",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[TranscriptionSummary],
                    parse_obj_as(
                        type_=typing.List[TranscriptionSummary],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise AuthenticationError(headers=dict(_response.headers))
            if _response.status_code == 429:
                raise RateLimitError(headers=dict(_response.headers))
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
