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

import typing
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.pagination import AsyncPager, SyncPager
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.unchecked_base_model import construct_type
from ..requests.create_transfer_order_data import CreateTransferOrderDataParams
from ..requests.transfer_order_goods_receipt import TransferOrderGoodsReceiptParams
from ..requests.transfer_order_query import TransferOrderQueryParams
from ..requests.update_transfer_order_data import UpdateTransferOrderDataParams
from ..types.cancel_transfer_order_response import CancelTransferOrderResponse
from ..types.create_transfer_order_response import CreateTransferOrderResponse
from ..types.delete_transfer_order_response import DeleteTransferOrderResponse
from ..types.receive_transfer_order_response import ReceiveTransferOrderResponse
from ..types.retrieve_transfer_order_response import RetrieveTransferOrderResponse
from ..types.search_transfer_orders_response import SearchTransferOrdersResponse
from ..types.start_transfer_order_response import StartTransferOrderResponse
from ..types.transfer_order import TransferOrder
from ..types.update_transfer_order_response import UpdateTransferOrderResponse

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


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

    def create(
        self,
        *,
        idempotency_key: str,
        transfer_order: CreateTransferOrderDataParams,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CreateTransferOrderResponse]:
        """
        Creates a new transfer order in [DRAFT](entity:TransferOrderStatus) status. A transfer order represents the intent
        to move [CatalogItemVariation](entity:CatalogItemVariation)s from one [Location](entity:Location) to another.
        The source and destination locations must be different and must belong to your Square account.

        In [DRAFT](entity:TransferOrderStatus) status, you can:
        - Add or remove items
        - Modify quantities
        - Update shipping information
        - Delete the entire order via [DeleteTransferOrder](api-endpoint:TransferOrders-DeleteTransferOrder)

        The request requires source_location_id and destination_location_id.
        Inventory levels are not affected until the order is started via
        [StartTransferOrder](api-endpoint:TransferOrders-StartTransferOrder).

        Common integration points:
        - Sync with warehouse management systems
        - Automate regular stock transfers
        - Initialize transfers from inventory optimization systems

        Creates a [transfer_order.created](webhook:transfer_order.created) webhook event.

        Parameters
        ----------
        idempotency_key : str
            A unique string that identifies this CreateTransferOrder request. Keys can be
            any valid string but must be unique for every CreateTransferOrder request.

        transfer_order : CreateTransferOrderDataParams
            The transfer order to create

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

        Returns
        -------
        HttpResponse[CreateTransferOrderResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/transfer-orders",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "transfer_order": convert_and_respect_annotation_metadata(
                    object_=transfer_order, annotation=CreateTransferOrderDataParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateTransferOrderResponse,
                    construct_type(
                        type_=CreateTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 search(
        self,
        *,
        query: typing.Optional[TransferOrderQueryParams] = OMIT,
        cursor: typing.Optional[str] = OMIT,
        limit: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[TransferOrder, SearchTransferOrdersResponse]:
        """
        Searches for transfer orders using filters. Returns a paginated list of matching
        [TransferOrder](entity:TransferOrder)s sorted by creation date.

        Common search scenarios:
        - Find orders for a source [Location](entity:Location)
        - Find orders for a destination [Location](entity:Location)
        - Find orders in a particular [TransferOrderStatus](entity:TransferOrderStatus)

        Parameters
        ----------
        query : typing.Optional[TransferOrderQueryParams]
            The search query

        cursor : typing.Optional[str]
            Pagination cursor from a previous search response

        limit : typing.Optional[int]
            Maximum number of results to return (1-100)

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

        Returns
        -------
        SyncPager[TransferOrder, SearchTransferOrdersResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/transfer-orders/search",
            method="POST",
            json={
                "query": convert_and_respect_annotation_metadata(
                    object_=query, annotation=TransferOrderQueryParams, direction="write"
                ),
                "cursor": cursor,
                "limit": limit,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    SearchTransferOrdersResponse,
                    construct_type(
                        type_=SearchTransferOrdersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.transfer_orders
                _parsed_next = _parsed_response.cursor
                _has_next = _parsed_next is not None and _parsed_next != ""
                _get_next = lambda: self.search(
                    query=query,
                    cursor=_parsed_next,
                    limit=limit,
                    request_options=request_options,
                )
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            _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(
        self, transfer_order_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[RetrieveTransferOrderResponse]:
        """
        Retrieves a specific [TransferOrder](entity:TransferOrder) by ID. Returns the complete
        order details including:

        - Basic information (status, dates, notes)
        - Line items with ordered and received quantities
        - Source and destination [Location](entity:Location)s
        - Tracking information (if available)

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to retrieve

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

        Returns
        -------
        HttpResponse[RetrieveTransferOrderResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RetrieveTransferOrderResponse,
                    construct_type(
                        type_=RetrieveTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 update(
        self,
        transfer_order_id: str,
        *,
        idempotency_key: str,
        transfer_order: UpdateTransferOrderDataParams,
        version: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UpdateTransferOrderResponse]:
        """
        Updates an existing transfer order. This endpoint supports sparse updates,
        allowing you to modify specific fields without affecting others.

        Creates a [transfer_order.updated](webhook:transfer_order.updated) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to update

        idempotency_key : str
            A unique string that identifies this UpdateTransferOrder request. Keys must contain only alphanumeric characters, dashes and underscores

        transfer_order : UpdateTransferOrderDataParams
            The transfer order updates to apply

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        HttpResponse[UpdateTransferOrderResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}",
            method="PUT",
            json={
                "idempotency_key": idempotency_key,
                "transfer_order": convert_and_respect_annotation_metadata(
                    object_=transfer_order, annotation=UpdateTransferOrderDataParams, direction="write"
                ),
                "version": version,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateTransferOrderResponse,
                    construct_type(
                        type_=UpdateTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 delete(
        self,
        transfer_order_id: str,
        *,
        version: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DeleteTransferOrderResponse]:
        """
        Deletes a transfer order in [DRAFT](entity:TransferOrderStatus) status.
        Only draft orders can be deleted. Once an order is started via
        [StartTransferOrder](api-endpoint:TransferOrders-StartTransferOrder), it can no longer be deleted.

        Creates a [transfer_order.deleted](webhook:transfer_order.deleted) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to delete

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        HttpResponse[DeleteTransferOrderResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}",
            method="DELETE",
            params={
                "version": version,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteTransferOrderResponse,
                    construct_type(
                        type_=DeleteTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 cancel(
        self,
        transfer_order_id: str,
        *,
        idempotency_key: str,
        version: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CancelTransferOrderResponse]:
        """
        Cancels a transfer order in [STARTED](entity:TransferOrderStatus) or
        [PARTIALLY_RECEIVED](entity:TransferOrderStatus) status. Any unreceived quantities will no
        longer be receivable and will be immediately returned to the source [Location](entity:Location)'s inventory.

        Common reasons for cancellation:
        - Items no longer needed at destination
        - Source location needs the inventory
        - Order created in error

        Creates a [transfer_order.updated](webhook:transfer_order.updated) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to cancel. Must be in STARTED or PARTIALLY_RECEIVED status.

        idempotency_key : str
            A unique string that identifies this UpdateTransferOrder request. Keys can be
            any valid string but must be unique for every UpdateTransferOrder request.

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        HttpResponse[CancelTransferOrderResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}/cancel",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "version": version,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelTransferOrderResponse,
                    construct_type(
                        type_=CancelTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 receive(
        self,
        transfer_order_id: str,
        *,
        idempotency_key: str,
        receipt: TransferOrderGoodsReceiptParams,
        version: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ReceiveTransferOrderResponse]:
        """
        Records receipt of [CatalogItemVariation](entity:CatalogItemVariation)s for a transfer order.
        This endpoint supports partial receiving - you can receive items in multiple batches.

        For each line item, you can specify:
        - Quantity received in good condition (added to destination inventory with [InventoryState](entity:InventoryState) of IN_STOCK)
        - Quantity damaged during transit/handling (added to destination inventory with [InventoryState](entity:InventoryState) of WASTE)
        - Quantity canceled (returned to source location's inventory)

        The order must be in [STARTED](entity:TransferOrderStatus) or [PARTIALLY_RECEIVED](entity:TransferOrderStatus) status.
        Received quantities are added to the destination [Location](entity:Location)'s inventory according to their condition.
        Canceled quantities are immediately returned to the source [Location](entity:Location)'s inventory.

        When all items are either received, damaged, or canceled, the order moves to
        [COMPLETED](entity:TransferOrderStatus) status.

        Creates a [transfer_order.updated](webhook:transfer_order.updated) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to receive items for

        idempotency_key : str
            A unique key to make this request idempotent

        receipt : TransferOrderGoodsReceiptParams
            The receipt details

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        HttpResponse[ReceiveTransferOrderResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}/receive",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "receipt": convert_and_respect_annotation_metadata(
                    object_=receipt, annotation=TransferOrderGoodsReceiptParams, direction="write"
                ),
                "version": version,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ReceiveTransferOrderResponse,
                    construct_type(
                        type_=ReceiveTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 start(
        self,
        transfer_order_id: str,
        *,
        idempotency_key: str,
        version: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[StartTransferOrderResponse]:
        """
        Changes a [DRAFT](entity:TransferOrderStatus) transfer order to [STARTED](entity:TransferOrderStatus) status.
        This decrements inventory at the source [Location](entity:Location) and marks it as in-transit.

        The order must be in [DRAFT](entity:TransferOrderStatus) status and have all required fields populated.
        Once started, the order can no longer be deleted, but it can be canceled via
        [CancelTransferOrder](api-endpoint:TransferOrders-CancelTransferOrder).

        Creates a [transfer_order.updated](webhook:transfer_order.updated) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to start. Must be in DRAFT status.

        idempotency_key : str
            A unique string that identifies this UpdateTransferOrder request. Keys can be
            any valid string but must be unique for every UpdateTransferOrder request.

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        HttpResponse[StartTransferOrderResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}/start",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "version": version,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    StartTransferOrderResponse,
                    construct_type(
                        type_=StartTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 AsyncRawTransferOrdersClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def create(
        self,
        *,
        idempotency_key: str,
        transfer_order: CreateTransferOrderDataParams,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CreateTransferOrderResponse]:
        """
        Creates a new transfer order in [DRAFT](entity:TransferOrderStatus) status. A transfer order represents the intent
        to move [CatalogItemVariation](entity:CatalogItemVariation)s from one [Location](entity:Location) to another.
        The source and destination locations must be different and must belong to your Square account.

        In [DRAFT](entity:TransferOrderStatus) status, you can:
        - Add or remove items
        - Modify quantities
        - Update shipping information
        - Delete the entire order via [DeleteTransferOrder](api-endpoint:TransferOrders-DeleteTransferOrder)

        The request requires source_location_id and destination_location_id.
        Inventory levels are not affected until the order is started via
        [StartTransferOrder](api-endpoint:TransferOrders-StartTransferOrder).

        Common integration points:
        - Sync with warehouse management systems
        - Automate regular stock transfers
        - Initialize transfers from inventory optimization systems

        Creates a [transfer_order.created](webhook:transfer_order.created) webhook event.

        Parameters
        ----------
        idempotency_key : str
            A unique string that identifies this CreateTransferOrder request. Keys can be
            any valid string but must be unique for every CreateTransferOrder request.

        transfer_order : CreateTransferOrderDataParams
            The transfer order to create

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

        Returns
        -------
        AsyncHttpResponse[CreateTransferOrderResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/transfer-orders",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "transfer_order": convert_and_respect_annotation_metadata(
                    object_=transfer_order, annotation=CreateTransferOrderDataParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateTransferOrderResponse,
                    construct_type(
                        type_=CreateTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 search(
        self,
        *,
        query: typing.Optional[TransferOrderQueryParams] = OMIT,
        cursor: typing.Optional[str] = OMIT,
        limit: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[TransferOrder, SearchTransferOrdersResponse]:
        """
        Searches for transfer orders using filters. Returns a paginated list of matching
        [TransferOrder](entity:TransferOrder)s sorted by creation date.

        Common search scenarios:
        - Find orders for a source [Location](entity:Location)
        - Find orders for a destination [Location](entity:Location)
        - Find orders in a particular [TransferOrderStatus](entity:TransferOrderStatus)

        Parameters
        ----------
        query : typing.Optional[TransferOrderQueryParams]
            The search query

        cursor : typing.Optional[str]
            Pagination cursor from a previous search response

        limit : typing.Optional[int]
            Maximum number of results to return (1-100)

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

        Returns
        -------
        AsyncPager[TransferOrder, SearchTransferOrdersResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/transfer-orders/search",
            method="POST",
            json={
                "query": convert_and_respect_annotation_metadata(
                    object_=query, annotation=TransferOrderQueryParams, direction="write"
                ),
                "cursor": cursor,
                "limit": limit,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    SearchTransferOrdersResponse,
                    construct_type(
                        type_=SearchTransferOrdersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.transfer_orders
                _parsed_next = _parsed_response.cursor
                _has_next = _parsed_next is not None and _parsed_next != ""

                async def _get_next():
                    return await self.search(
                        query=query,
                        cursor=_parsed_next,
                        limit=limit,
                        request_options=request_options,
                    )

                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            _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(
        self, transfer_order_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[RetrieveTransferOrderResponse]:
        """
        Retrieves a specific [TransferOrder](entity:TransferOrder) by ID. Returns the complete
        order details including:

        - Basic information (status, dates, notes)
        - Line items with ordered and received quantities
        - Source and destination [Location](entity:Location)s
        - Tracking information (if available)

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to retrieve

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

        Returns
        -------
        AsyncHttpResponse[RetrieveTransferOrderResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    RetrieveTransferOrderResponse,
                    construct_type(
                        type_=RetrieveTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 update(
        self,
        transfer_order_id: str,
        *,
        idempotency_key: str,
        transfer_order: UpdateTransferOrderDataParams,
        version: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UpdateTransferOrderResponse]:
        """
        Updates an existing transfer order. This endpoint supports sparse updates,
        allowing you to modify specific fields without affecting others.

        Creates a [transfer_order.updated](webhook:transfer_order.updated) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to update

        idempotency_key : str
            A unique string that identifies this UpdateTransferOrder request. Keys must contain only alphanumeric characters, dashes and underscores

        transfer_order : UpdateTransferOrderDataParams
            The transfer order updates to apply

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        AsyncHttpResponse[UpdateTransferOrderResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}",
            method="PUT",
            json={
                "idempotency_key": idempotency_key,
                "transfer_order": convert_and_respect_annotation_metadata(
                    object_=transfer_order, annotation=UpdateTransferOrderDataParams, direction="write"
                ),
                "version": version,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateTransferOrderResponse,
                    construct_type(
                        type_=UpdateTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 delete(
        self,
        transfer_order_id: str,
        *,
        version: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DeleteTransferOrderResponse]:
        """
        Deletes a transfer order in [DRAFT](entity:TransferOrderStatus) status.
        Only draft orders can be deleted. Once an order is started via
        [StartTransferOrder](api-endpoint:TransferOrders-StartTransferOrder), it can no longer be deleted.

        Creates a [transfer_order.deleted](webhook:transfer_order.deleted) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to delete

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        AsyncHttpResponse[DeleteTransferOrderResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}",
            method="DELETE",
            params={
                "version": version,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteTransferOrderResponse,
                    construct_type(
                        type_=DeleteTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 cancel(
        self,
        transfer_order_id: str,
        *,
        idempotency_key: str,
        version: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CancelTransferOrderResponse]:
        """
        Cancels a transfer order in [STARTED](entity:TransferOrderStatus) or
        [PARTIALLY_RECEIVED](entity:TransferOrderStatus) status. Any unreceived quantities will no
        longer be receivable and will be immediately returned to the source [Location](entity:Location)'s inventory.

        Common reasons for cancellation:
        - Items no longer needed at destination
        - Source location needs the inventory
        - Order created in error

        Creates a [transfer_order.updated](webhook:transfer_order.updated) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to cancel. Must be in STARTED or PARTIALLY_RECEIVED status.

        idempotency_key : str
            A unique string that identifies this UpdateTransferOrder request. Keys can be
            any valid string but must be unique for every UpdateTransferOrder request.

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        AsyncHttpResponse[CancelTransferOrderResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}/cancel",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "version": version,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelTransferOrderResponse,
                    construct_type(
                        type_=CancelTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 receive(
        self,
        transfer_order_id: str,
        *,
        idempotency_key: str,
        receipt: TransferOrderGoodsReceiptParams,
        version: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ReceiveTransferOrderResponse]:
        """
        Records receipt of [CatalogItemVariation](entity:CatalogItemVariation)s for a transfer order.
        This endpoint supports partial receiving - you can receive items in multiple batches.

        For each line item, you can specify:
        - Quantity received in good condition (added to destination inventory with [InventoryState](entity:InventoryState) of IN_STOCK)
        - Quantity damaged during transit/handling (added to destination inventory with [InventoryState](entity:InventoryState) of WASTE)
        - Quantity canceled (returned to source location's inventory)

        The order must be in [STARTED](entity:TransferOrderStatus) or [PARTIALLY_RECEIVED](entity:TransferOrderStatus) status.
        Received quantities are added to the destination [Location](entity:Location)'s inventory according to their condition.
        Canceled quantities are immediately returned to the source [Location](entity:Location)'s inventory.

        When all items are either received, damaged, or canceled, the order moves to
        [COMPLETED](entity:TransferOrderStatus) status.

        Creates a [transfer_order.updated](webhook:transfer_order.updated) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to receive items for

        idempotency_key : str
            A unique key to make this request idempotent

        receipt : TransferOrderGoodsReceiptParams
            The receipt details

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        AsyncHttpResponse[ReceiveTransferOrderResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}/receive",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "receipt": convert_and_respect_annotation_metadata(
                    object_=receipt, annotation=TransferOrderGoodsReceiptParams, direction="write"
                ),
                "version": version,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ReceiveTransferOrderResponse,
                    construct_type(
                        type_=ReceiveTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 start(
        self,
        transfer_order_id: str,
        *,
        idempotency_key: str,
        version: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[StartTransferOrderResponse]:
        """
        Changes a [DRAFT](entity:TransferOrderStatus) transfer order to [STARTED](entity:TransferOrderStatus) status.
        This decrements inventory at the source [Location](entity:Location) and marks it as in-transit.

        The order must be in [DRAFT](entity:TransferOrderStatus) status and have all required fields populated.
        Once started, the order can no longer be deleted, but it can be canceled via
        [CancelTransferOrder](api-endpoint:TransferOrders-CancelTransferOrder).

        Creates a [transfer_order.updated](webhook:transfer_order.updated) webhook event.

        Parameters
        ----------
        transfer_order_id : str
            The ID of the transfer order to start. Must be in DRAFT status.

        idempotency_key : str
            A unique string that identifies this UpdateTransferOrder request. Keys can be
            any valid string but must be unique for every UpdateTransferOrder request.

        version : typing.Optional[int]
            Version for optimistic concurrency

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

        Returns
        -------
        AsyncHttpResponse[StartTransferOrderResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/transfer-orders/{jsonable_encoder(transfer_order_id)}/start",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "version": version,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    StartTransferOrderResponse,
                    construct_type(
                        type_=StartTransferOrderResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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)
