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

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..types.v_1_detokenize_record_request import V1DetokenizeRecordRequest
from ..core.request_options import RequestOptions
from ..types.v_1_detokenize_response import V1DetokenizeResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.pydantic_utilities import parse_obj_as
from ..errors.not_found_error import NotFoundError
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..types.v_1_get_query_response import V1GetQueryResponse
from ..types.v_1_tokenize_record_request import V1TokenizeRecordRequest
from ..types.v_1_tokenize_response import V1TokenizeResponse
from .types.vault_get_request_redaction import VaultGetRequestRedaction
from .types.vault_get_request_order_by import VaultGetRequestOrderBy
from ..types.v_1_bulk_get_record_response import V1BulkGetRecordResponse
from ..types.v_1_field_records import V1FieldRecords
from ..types.v_1_byot import V1Byot
from ..types.v_1_insert_record_response import V1InsertRecordResponse
from ..types.v_1_bulk_delete_record_response import V1BulkDeleteRecordResponse
from .types.vault_get_by_id_request_redaction import VaultGetByIdRequestRedaction
from ..types.v_1_update_record_response import V1UpdateRecordResponse
from ..types.v_1_delete_record_response import V1DeleteRecordResponse
from .. import core
from ..types.v_1_delete_file_response import V1DeleteFileResponse
from ..types.v_1_get_file_scan_status_response import V1GetFileScanStatusResponse
from ..core.client_wrapper import AsyncClientWrapper

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


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

    def detokenize(
        self,
        vault_id: str,
        *,
        detokenization_parameters: typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]] = OMIT,
        download_url: typing.Optional[bool] = OMIT,
        continue_on_error: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1DetokenizeResponse:
        """
        Returns records that correspond to the specified tokens.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        detokenization_parameters : typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]]
            Detokenization details.

        download_url : typing.Optional[bool]
            If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.

        continue_on_error : typing.Optional[bool]
            If `true`, the detokenization request continues even if an error occurs.

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

        Returns
        -------
        V1DetokenizeResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow, V1DetokenizeRecordRequest

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.detokenize(
            vault_id="vaultID",
            detokenization_parameters=[
                V1DetokenizeRecordRequest(
                    token="afbd1074-51c1-4a16-9eee-e2c0ecb52125",
                    redaction="PLAIN_TEXT",
                ),
                V1DetokenizeRecordRequest(
                    token="05383487-fcae-42e5-a48e-5bd62a51af12",
                    redaction="DEFAULT",
                ),
            ],
            download_url=False,
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/detokenize",
            method="POST",
            json={
                "detokenizationParameters": convert_and_respect_annotation_metadata(
                    object_=detokenization_parameters,
                    annotation=typing.Sequence[V1DetokenizeRecordRequest],
                    direction="write",
                ),
                "downloadURL": download_url,
                "continueOnError": continue_on_error,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1DetokenizeResponse,
                    parse_obj_as(
                        type_=V1DetokenizeResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def execute_query(
        self,
        vault_id: str,
        *,
        query: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1GetQueryResponse:
        """
        Returns records for a valid SQL query. This endpoint <ul><li>Can return redacted record values.</li><li>Supports only the <code>SELECT</code> command.</li><li>Returns a maximum of 25 records. To return additional records, perform another query using the <code>OFFSET</code> keyword.</li><li>Can't modify the vault or perform transactions.</li><li>Can't return tokens.</li><li>Can't return file download or render URLs.</li><li>Doesn't support the <code>WHERE</code> keyword with columns using transient tokenization.</li><li>Doesn't support `?` conditional for columns with column-level encryption disabled.</li><ul>

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        query : typing.Optional[str]
            The SQL query to execute.<br><br><b>Supported commands:</b> <ul> <li><code>SELECT</code></li> </ul> <b>Supported operators:</b> <ul> <li><code>&gt;</code></li> <li><code>&lt;</code></li> <li><code>=</code></li> <li><code>AND</code></li> <li><code>OR</code></li> <li><code>NOT</code></li> <li><code>LIKE</code></li> <li><code>ILIKE</code></li> <li><code>NULL</code></li> <li><code>NOT NULL</code></li> </ul> <b>Supported keywords:</b> <ul> <li><code>FROM</code></li> <li><code>JOIN</code></li> <li><code>INNER JOIN</code></li> <li><code>LEFT OUTER JOIN</code></li> <li><code>LEFT JOIN</code></li> <li><code>RIGHT OUTER JOIN</code></li> <li><code>RIGHT JOIN</code></li> <li><code>FULL OUTER JOIN</code></li> <li><code>FULL JOIN</code></li> <li><code>OFFSET</code></li> <li><code>LIMIT</code></li> <li><code>WHERE</code></li> </ul> <b>Supported functions:</b> <ul> <li><code>AVG()</code></li> <li><code>SUM()</code></li> <li><code>COUNT()</code></li> <li><code>MIN()</code></li> <li><code>MAX()</code></li> <li><code>REDACTION()</code></li> </ul>

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

        Returns
        -------
        V1GetQueryResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.execute_query(
            vault_id="vaultID",
            query='select * from opportunities where id="01010000ade21cded569d43944544ec6"',
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/query",
            method="POST",
            json={
                "query": query,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1GetQueryResponse,
                    parse_obj_as(
                        type_=V1GetQueryResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def tokenize(
        self,
        vault_id: str,
        *,
        tokenization_parameters: typing.Optional[typing.Sequence[V1TokenizeRecordRequest]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1TokenizeResponse:
        """
        Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.<br /><br /><b>Note:</b> This endpoint doesn't insert records—it returns tokens for existing values. To insert records and tokenize that new record's values, see <a href='#RecordService_InsertRecord'>Insert Record</a> and the tokenization parameter.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        tokenization_parameters : typing.Optional[typing.Sequence[V1TokenizeRecordRequest]]
            Tokenization details.

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

        Returns
        -------
        V1TokenizeResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.tokenize(
            vault_id="vaultID",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/tokenize",
            method="POST",
            json={
                "tokenizationParameters": convert_and_respect_annotation_metadata(
                    object_=tokenization_parameters,
                    annotation=typing.Sequence[V1TokenizeRecordRequest],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1TokenizeResponse,
                    parse_obj_as(
                        type_=V1TokenizeResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self,
        vault_id: str,
        object_name: str,
        *,
        skyflow_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        redaction: typing.Optional[VaultGetRequestRedaction] = None,
        tokenization: typing.Optional[bool] = None,
        fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        offset: typing.Optional[int] = None,
        limit: typing.Optional[str] = None,
        download_url: typing.Optional[bool] = None,
        column_name: typing.Optional[str] = None,
        column_values: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        order_by: typing.Optional[VaultGetRequestOrderBy] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1BulkGetRecordResponse:
        """
        Gets the specified records from a table.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table that contains the records.

        skyflow_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            `skyflow_id` values of the records to return, with one value per `skyflow_ids` URL parameter. For example, `?skyflow_ids=abc&skyflow_ids=123`.<br /><br />If not specified, returns the first 25 records in the table.

        redaction : typing.Optional[VaultGetRequestRedaction]
            Redaction level to enforce for the returned records. Subject to policies assigned to the API caller.

        tokenization : typing.Optional[bool]
            If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.

        fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.<br /><br />If not specified, returns all fields.

        offset : typing.Optional[int]
            Record position at which to start receiving data.

        limit : typing.Optional[str]
            Number of record to return. Maximum 25.

        download_url : typing.Optional[bool]
            If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.

        column_name : typing.Optional[str]
            Name of the column. It must be configured as unique in the schema. If you provide both column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.

        column_values : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Column values of the records to return, with one value per `column_values` URL parameter. For example, `?column_values=abc&column_values=123`.<br /><br />`column_name` is mandatory when providing `column_values`. If you use column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.

        order_by : typing.Optional[VaultGetRequestOrderBy]
            Order to return records, based on `skyflow_id` values. To disable, set to `NONE`.

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

        Returns
        -------
        V1BulkGetRecordResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.get(
            vault_id="vaultID",
            object_name="objectName",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
            method="GET",
            params={
                "skyflow_ids": skyflow_ids,
                "redaction": redaction,
                "tokenization": tokenization,
                "fields": fields,
                "offset": offset,
                "limit": limit,
                "downloadURL": download_url,
                "column_name": column_name,
                "column_values": column_values,
                "order_by": order_by,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1BulkGetRecordResponse,
                    parse_obj_as(
                        type_=V1BulkGetRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def insert(
        self,
        vault_id: str,
        object_name: str,
        *,
        records: typing.Optional[typing.Sequence[V1FieldRecords]] = OMIT,
        tokenization: typing.Optional[bool] = OMIT,
        upsert: typing.Optional[str] = OMIT,
        homogeneous: typing.Optional[bool] = OMIT,
        byot: typing.Optional[V1Byot] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1InsertRecordResponse:
        """
        Inserts a record in the specified table.<br /><br />The time-to-live (TTL) for a transient field begins when the field value is set during record insertion.<br /><br />Columns that have a string data type and a uniqueness constraint accept strings up to 2500 characters. If an inserted string exceeds 2500 characters, the call returns a token insertion error.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        records : typing.Optional[typing.Sequence[V1FieldRecords]]
            Record values and tokens.

        tokenization : typing.Optional[bool]
            If `true`, this operation returns tokens for fields with tokenization enabled.

        upsert : typing.Optional[str]
            Name of a unique column in the table. Uses upsert operations to check if a record exists based on the unique column's value. If a matching record exists, the record updates with the values you provide. If a matching record doesn't exist, the upsert operation inserts a new record.<br /><br />When you upsert a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.

        homogeneous : typing.Optional[bool]
            If `true`, this operation mandates that all the records have the same fields. This parameter does not work with upsert.

        byot : typing.Optional[V1Byot]

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

        Returns
        -------
        V1InsertRecordResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow, V1FieldRecords

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.insert(
            vault_id="vaultID",
            object_name="objectName",
            records=[
                V1FieldRecords(
                    fields={
                        "drivers_license_number": "13456789",
                        "name": "John",
                        "phone_number": "1236784563",
                        "ssn": "123-45-6789",
                    },
                ),
                V1FieldRecords(
                    fields={
                        "drivers_license_number": "98765432",
                        "name": "James",
                        "phone_number": "9876543215",
                        "ssn": "345-45-9876",
                    },
                ),
            ],
            tokenization=True,
            upsert="drivers_license_number",
            homogeneous=False,
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
            method="POST",
            json={
                "records": convert_and_respect_annotation_metadata(
                    object_=records, annotation=typing.Sequence[V1FieldRecords], direction="write"
                ),
                "tokenization": tokenization,
                "upsert": upsert,
                "homogeneous": homogeneous,
                "byot": byot,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1InsertRecordResponse,
                    parse_obj_as(
                        type_=V1InsertRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete(
        self,
        vault_id: str,
        object_name: str,
        *,
        skyflow_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1BulkDeleteRecordResponse:
        """
        Deletes the specified records from a table.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        skyflow_ids : typing.Optional[typing.Sequence[str]]
            `skyflow_id` values of the records to delete. If `*` is specified, this operation deletes all records in the table.

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

        Returns
        -------
        V1BulkDeleteRecordResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.delete(
            vault_id="vaultID",
            object_name="objectName",
            skyflow_ids=[
                "51782ea4-91a5-4430-a06d-f4b76efd3d2f",
                "110ce08f-6059-4874-b1ae-7c6651d286ff",
            ],
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
            method="DELETE",
            json={
                "skyflow_ids": skyflow_ids,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1BulkDeleteRecordResponse,
                    parse_obj_as(
                        type_=V1BulkDeleteRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get_by_id(
        self,
        vault_id: str,
        object_name: str,
        id: str,
        *,
        redaction: typing.Optional[VaultGetByIdRequestRedaction] = None,
        tokenization: typing.Optional[bool] = None,
        fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        download_url: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1FieldRecords:
        """
        Returns the specified record from a table.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        redaction : typing.Optional[VaultGetByIdRequestRedaction]
            Redaction level to enforce for the returned record. Subject to policies assigned to the API caller.

        tokenization : typing.Optional[bool]
            If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.

        fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.<br /><br />If not specified, returns all fields.

        download_url : typing.Optional[bool]
            If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.

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

        Returns
        -------
        V1FieldRecords
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.get_by_id(
            vault_id="vaultID",
            object_name="objectName",
            id="ID",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
            method="GET",
            params={
                "redaction": redaction,
                "tokenization": tokenization,
                "fields": fields,
                "downloadURL": download_url,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1FieldRecords,
                    parse_obj_as(
                        type_=V1FieldRecords,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update_by_id(
        self,
        vault_id: str,
        object_name: str,
        id: str,
        *,
        record: typing.Optional[V1FieldRecords] = OMIT,
        tokenization: typing.Optional[bool] = OMIT,
        byot: typing.Optional[V1Byot] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1UpdateRecordResponse:
        """
        Updates the specified record in a table.<br /><br />When you update a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.<br /><br />The time-to-live (TTL) for a transient field resets when the field value is updated.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        record : typing.Optional[V1FieldRecords]

        tokenization : typing.Optional[bool]
            If `true`, this operation returns tokens for fields with tokenization enabled.

        byot : typing.Optional[V1Byot]

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

        Returns
        -------
        V1UpdateRecordResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow, V1FieldRecords

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.update_by_id(
            vault_id="vaultID",
            object_name="objectName",
            id="ID",
            record=V1FieldRecords(
                fields={
                    "drivers_license_number": "89867453",
                    "name": "Steve Smith",
                    "phone_number": "8794523160",
                    "ssn": "143-89-2306",
                },
            ),
            tokenization=True,
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
            method="PUT",
            json={
                "record": convert_and_respect_annotation_metadata(
                    object_=record, annotation=V1FieldRecords, direction="write"
                ),
                "tokenization": tokenization,
                "byot": byot,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1UpdateRecordResponse,
                    parse_obj_as(
                        type_=V1UpdateRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete_by_id(
        self, vault_id: str, object_name: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> V1DeleteRecordResponse:
        """
        Deletes the specified record from a table.<br /><br /><b>Note:</b> This method doesn't delete transient field tokens. Transient field values are available until they expire based on the fields' time-to-live (TTL) setting.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record to delete.

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

        Returns
        -------
        V1DeleteRecordResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.delete_by_id(
            vault_id="vaultID",
            object_name="objectName",
            id="ID",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1DeleteRecordResponse,
                    parse_obj_as(
                        type_=V1DeleteRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def upload_files(
        self,
        vault_id: str,
        object_name: str,
        id: str,
        *,
        file_column_name: typing.Optional[core.File] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1UpdateRecordResponse:
        """
        Uploads a file to the specified record.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        file_column_name : typing.Optional[core.File]
            See core.File for more documentation

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

        Returns
        -------
        V1UpdateRecordResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.upload_files(
            vault_id="vaultID",
            object_name="objectName",
            id="ID",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}/files",
            method="POST",
            data={},
            files={
                "fileColumnName": file_column_name,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1UpdateRecordResponse,
                    parse_obj_as(
                        type_=V1UpdateRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete_file(
        self,
        vault_id: str,
        table_name: str,
        id: str,
        column_name: str,
        *,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1DeleteFileResponse:
        """
        Deletes a file from the specified record.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        table_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        column_name : str
            Name of the column that contains the file.

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

        Returns
        -------
        V1DeleteFileResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.delete_file(
            vault_id="vaultID",
            table_name="tableName",
            id="ID",
            column_name="columnName",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(table_name)}/{jsonable_encoder(id)}/files/{jsonable_encoder(column_name)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1DeleteFileResponse,
                    parse_obj_as(
                        type_=V1DeleteFileResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get_file_scan_status(
        self,
        vault_id: str,
        table_name: str,
        id: str,
        column_name: str,
        *,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1GetFileScanStatusResponse:
        """
        Returns the anti-virus scan status of a file.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        table_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        column_name : str
            Name of the column that contains the file.

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

        Returns
        -------
        V1GetFileScanStatusResponse
            A successful response.

        Examples
        --------
        from skyflow import Skyflow

        client = Skyflow(
            api_key="YOUR_API_KEY",
        )
        client.vault.get_file_scan_status(
            vault_id="vaultID",
            table_name="tableName",
            id="ID",
            column_name="columnName",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(table_name)}/{jsonable_encoder(id)}/files/{jsonable_encoder(column_name)}/scan-status",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1GetFileScanStatusResponse,
                    parse_obj_as(
                        type_=V1GetFileScanStatusResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def detokenize(
        self,
        vault_id: str,
        *,
        detokenization_parameters: typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]] = OMIT,
        download_url: typing.Optional[bool] = OMIT,
        continue_on_error: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1DetokenizeResponse:
        """
        Returns records that correspond to the specified tokens.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        detokenization_parameters : typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]]
            Detokenization details.

        download_url : typing.Optional[bool]
            If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.

        continue_on_error : typing.Optional[bool]
            If `true`, the detokenization request continues even if an error occurs.

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

        Returns
        -------
        V1DetokenizeResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow, V1DetokenizeRecordRequest

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.detokenize(
                vault_id="vaultID",
                detokenization_parameters=[
                    V1DetokenizeRecordRequest(
                        token="afbd1074-51c1-4a16-9eee-e2c0ecb52125",
                        redaction="PLAIN_TEXT",
                    ),
                    V1DetokenizeRecordRequest(
                        token="05383487-fcae-42e5-a48e-5bd62a51af12",
                        redaction="DEFAULT",
                    ),
                ],
                download_url=False,
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/detokenize",
            method="POST",
            json={
                "detokenizationParameters": convert_and_respect_annotation_metadata(
                    object_=detokenization_parameters,
                    annotation=typing.Sequence[V1DetokenizeRecordRequest],
                    direction="write",
                ),
                "downloadURL": download_url,
                "continueOnError": continue_on_error,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1DetokenizeResponse,
                    parse_obj_as(
                        type_=V1DetokenizeResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def execute_query(
        self,
        vault_id: str,
        *,
        query: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1GetQueryResponse:
        """
        Returns records for a valid SQL query. This endpoint <ul><li>Can return redacted record values.</li><li>Supports only the <code>SELECT</code> command.</li><li>Returns a maximum of 25 records. To return additional records, perform another query using the <code>OFFSET</code> keyword.</li><li>Can't modify the vault or perform transactions.</li><li>Can't return tokens.</li><li>Can't return file download or render URLs.</li><li>Doesn't support the <code>WHERE</code> keyword with columns using transient tokenization.</li><li>Doesn't support `?` conditional for columns with column-level encryption disabled.</li><ul>

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        query : typing.Optional[str]
            The SQL query to execute.<br><br><b>Supported commands:</b> <ul> <li><code>SELECT</code></li> </ul> <b>Supported operators:</b> <ul> <li><code>&gt;</code></li> <li><code>&lt;</code></li> <li><code>=</code></li> <li><code>AND</code></li> <li><code>OR</code></li> <li><code>NOT</code></li> <li><code>LIKE</code></li> <li><code>ILIKE</code></li> <li><code>NULL</code></li> <li><code>NOT NULL</code></li> </ul> <b>Supported keywords:</b> <ul> <li><code>FROM</code></li> <li><code>JOIN</code></li> <li><code>INNER JOIN</code></li> <li><code>LEFT OUTER JOIN</code></li> <li><code>LEFT JOIN</code></li> <li><code>RIGHT OUTER JOIN</code></li> <li><code>RIGHT JOIN</code></li> <li><code>FULL OUTER JOIN</code></li> <li><code>FULL JOIN</code></li> <li><code>OFFSET</code></li> <li><code>LIMIT</code></li> <li><code>WHERE</code></li> </ul> <b>Supported functions:</b> <ul> <li><code>AVG()</code></li> <li><code>SUM()</code></li> <li><code>COUNT()</code></li> <li><code>MIN()</code></li> <li><code>MAX()</code></li> <li><code>REDACTION()</code></li> </ul>

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

        Returns
        -------
        V1GetQueryResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.execute_query(
                vault_id="vaultID",
                query='select * from opportunities where id="01010000ade21cded569d43944544ec6"',
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/query",
            method="POST",
            json={
                "query": query,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1GetQueryResponse,
                    parse_obj_as(
                        type_=V1GetQueryResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def tokenize(
        self,
        vault_id: str,
        *,
        tokenization_parameters: typing.Optional[typing.Sequence[V1TokenizeRecordRequest]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1TokenizeResponse:
        """
        Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.<br /><br /><b>Note:</b> This endpoint doesn't insert records—it returns tokens for existing values. To insert records and tokenize that new record's values, see <a href='#RecordService_InsertRecord'>Insert Record</a> and the tokenization parameter.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        tokenization_parameters : typing.Optional[typing.Sequence[V1TokenizeRecordRequest]]
            Tokenization details.

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

        Returns
        -------
        V1TokenizeResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.tokenize(
                vault_id="vaultID",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/tokenize",
            method="POST",
            json={
                "tokenizationParameters": convert_and_respect_annotation_metadata(
                    object_=tokenization_parameters,
                    annotation=typing.Sequence[V1TokenizeRecordRequest],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1TokenizeResponse,
                    parse_obj_as(
                        type_=V1TokenizeResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self,
        vault_id: str,
        object_name: str,
        *,
        skyflow_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        redaction: typing.Optional[VaultGetRequestRedaction] = None,
        tokenization: typing.Optional[bool] = None,
        fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        offset: typing.Optional[int] = None,
        limit: typing.Optional[str] = None,
        download_url: typing.Optional[bool] = None,
        column_name: typing.Optional[str] = None,
        column_values: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        order_by: typing.Optional[VaultGetRequestOrderBy] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1BulkGetRecordResponse:
        """
        Gets the specified records from a table.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table that contains the records.

        skyflow_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            `skyflow_id` values of the records to return, with one value per `skyflow_ids` URL parameter. For example, `?skyflow_ids=abc&skyflow_ids=123`.<br /><br />If not specified, returns the first 25 records in the table.

        redaction : typing.Optional[VaultGetRequestRedaction]
            Redaction level to enforce for the returned records. Subject to policies assigned to the API caller.

        tokenization : typing.Optional[bool]
            If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.

        fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.<br /><br />If not specified, returns all fields.

        offset : typing.Optional[int]
            Record position at which to start receiving data.

        limit : typing.Optional[str]
            Number of record to return. Maximum 25.

        download_url : typing.Optional[bool]
            If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.

        column_name : typing.Optional[str]
            Name of the column. It must be configured as unique in the schema. If you provide both column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.

        column_values : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Column values of the records to return, with one value per `column_values` URL parameter. For example, `?column_values=abc&column_values=123`.<br /><br />`column_name` is mandatory when providing `column_values`. If you use column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.

        order_by : typing.Optional[VaultGetRequestOrderBy]
            Order to return records, based on `skyflow_id` values. To disable, set to `NONE`.

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

        Returns
        -------
        V1BulkGetRecordResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.get(
                vault_id="vaultID",
                object_name="objectName",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
            method="GET",
            params={
                "skyflow_ids": skyflow_ids,
                "redaction": redaction,
                "tokenization": tokenization,
                "fields": fields,
                "offset": offset,
                "limit": limit,
                "downloadURL": download_url,
                "column_name": column_name,
                "column_values": column_values,
                "order_by": order_by,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1BulkGetRecordResponse,
                    parse_obj_as(
                        type_=V1BulkGetRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def insert(
        self,
        vault_id: str,
        object_name: str,
        *,
        records: typing.Optional[typing.Sequence[V1FieldRecords]] = OMIT,
        tokenization: typing.Optional[bool] = OMIT,
        upsert: typing.Optional[str] = OMIT,
        homogeneous: typing.Optional[bool] = OMIT,
        byot: typing.Optional[V1Byot] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1InsertRecordResponse:
        """
        Inserts a record in the specified table.<br /><br />The time-to-live (TTL) for a transient field begins when the field value is set during record insertion.<br /><br />Columns that have a string data type and a uniqueness constraint accept strings up to 2500 characters. If an inserted string exceeds 2500 characters, the call returns a token insertion error.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        records : typing.Optional[typing.Sequence[V1FieldRecords]]
            Record values and tokens.

        tokenization : typing.Optional[bool]
            If `true`, this operation returns tokens for fields with tokenization enabled.

        upsert : typing.Optional[str]
            Name of a unique column in the table. Uses upsert operations to check if a record exists based on the unique column's value. If a matching record exists, the record updates with the values you provide. If a matching record doesn't exist, the upsert operation inserts a new record.<br /><br />When you upsert a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.

        homogeneous : typing.Optional[bool]
            If `true`, this operation mandates that all the records have the same fields. This parameter does not work with upsert.

        byot : typing.Optional[V1Byot]

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

        Returns
        -------
        V1InsertRecordResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow, V1FieldRecords

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.insert(
                vault_id="vaultID",
                object_name="objectName",
                records=[
                    V1FieldRecords(
                        fields={
                            "drivers_license_number": "13456789",
                            "name": "John",
                            "phone_number": "1236784563",
                            "ssn": "123-45-6789",
                        },
                    ),
                    V1FieldRecords(
                        fields={
                            "drivers_license_number": "98765432",
                            "name": "James",
                            "phone_number": "9876543215",
                            "ssn": "345-45-9876",
                        },
                    ),
                ],
                tokenization=True,
                upsert="drivers_license_number",
                homogeneous=False,
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
            method="POST",
            json={
                "records": convert_and_respect_annotation_metadata(
                    object_=records, annotation=typing.Sequence[V1FieldRecords], direction="write"
                ),
                "tokenization": tokenization,
                "upsert": upsert,
                "homogeneous": homogeneous,
                "byot": byot,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1InsertRecordResponse,
                    parse_obj_as(
                        type_=V1InsertRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete(
        self,
        vault_id: str,
        object_name: str,
        *,
        skyflow_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1BulkDeleteRecordResponse:
        """
        Deletes the specified records from a table.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        skyflow_ids : typing.Optional[typing.Sequence[str]]
            `skyflow_id` values of the records to delete. If `*` is specified, this operation deletes all records in the table.

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

        Returns
        -------
        V1BulkDeleteRecordResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.delete(
                vault_id="vaultID",
                object_name="objectName",
                skyflow_ids=[
                    "51782ea4-91a5-4430-a06d-f4b76efd3d2f",
                    "110ce08f-6059-4874-b1ae-7c6651d286ff",
                ],
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
            method="DELETE",
            json={
                "skyflow_ids": skyflow_ids,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1BulkDeleteRecordResponse,
                    parse_obj_as(
                        type_=V1BulkDeleteRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get_by_id(
        self,
        vault_id: str,
        object_name: str,
        id: str,
        *,
        redaction: typing.Optional[VaultGetByIdRequestRedaction] = None,
        tokenization: typing.Optional[bool] = None,
        fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        download_url: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1FieldRecords:
        """
        Returns the specified record from a table.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        redaction : typing.Optional[VaultGetByIdRequestRedaction]
            Redaction level to enforce for the returned record. Subject to policies assigned to the API caller.

        tokenization : typing.Optional[bool]
            If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.

        fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.<br /><br />If not specified, returns all fields.

        download_url : typing.Optional[bool]
            If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.

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

        Returns
        -------
        V1FieldRecords
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.get_by_id(
                vault_id="vaultID",
                object_name="objectName",
                id="ID",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
            method="GET",
            params={
                "redaction": redaction,
                "tokenization": tokenization,
                "fields": fields,
                "downloadURL": download_url,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1FieldRecords,
                    parse_obj_as(
                        type_=V1FieldRecords,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update_by_id(
        self,
        vault_id: str,
        object_name: str,
        id: str,
        *,
        record: typing.Optional[V1FieldRecords] = OMIT,
        tokenization: typing.Optional[bool] = OMIT,
        byot: typing.Optional[V1Byot] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1UpdateRecordResponse:
        """
        Updates the specified record in a table.<br /><br />When you update a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.<br /><br />The time-to-live (TTL) for a transient field resets when the field value is updated.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        record : typing.Optional[V1FieldRecords]

        tokenization : typing.Optional[bool]
            If `true`, this operation returns tokens for fields with tokenization enabled.

        byot : typing.Optional[V1Byot]

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

        Returns
        -------
        V1UpdateRecordResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow, V1FieldRecords

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.update_by_id(
                vault_id="vaultID",
                object_name="objectName",
                id="ID",
                record=V1FieldRecords(
                    fields={
                        "drivers_license_number": "89867453",
                        "name": "Steve Smith",
                        "phone_number": "8794523160",
                        "ssn": "143-89-2306",
                    },
                ),
                tokenization=True,
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
            method="PUT",
            json={
                "record": convert_and_respect_annotation_metadata(
                    object_=record, annotation=V1FieldRecords, direction="write"
                ),
                "tokenization": tokenization,
                "byot": byot,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1UpdateRecordResponse,
                    parse_obj_as(
                        type_=V1UpdateRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete_by_id(
        self, vault_id: str, object_name: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> V1DeleteRecordResponse:
        """
        Deletes the specified record from a table.<br /><br /><b>Note:</b> This method doesn't delete transient field tokens. Transient field values are available until they expire based on the fields' time-to-live (TTL) setting.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record to delete.

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

        Returns
        -------
        V1DeleteRecordResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.delete_by_id(
                vault_id="vaultID",
                object_name="objectName",
                id="ID",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1DeleteRecordResponse,
                    parse_obj_as(
                        type_=V1DeleteRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def upload_files(
        self,
        vault_id: str,
        object_name: str,
        id: str,
        *,
        file_column_name: typing.Optional[core.File] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1UpdateRecordResponse:
        """
        Uploads a file to the specified record.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        object_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        file_column_name : typing.Optional[core.File]
            See core.File for more documentation

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

        Returns
        -------
        V1UpdateRecordResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.upload_files(
                vault_id="vaultID",
                object_name="objectName",
                id="ID",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}/files",
            method="POST",
            data={},
            files={
                "fileColumnName": file_column_name,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1UpdateRecordResponse,
                    parse_obj_as(
                        type_=V1UpdateRecordResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete_file(
        self,
        vault_id: str,
        table_name: str,
        id: str,
        column_name: str,
        *,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1DeleteFileResponse:
        """
        Deletes a file from the specified record.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        table_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        column_name : str
            Name of the column that contains the file.

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

        Returns
        -------
        V1DeleteFileResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.delete_file(
                vault_id="vaultID",
                table_name="tableName",
                id="ID",
                column_name="columnName",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(table_name)}/{jsonable_encoder(id)}/files/{jsonable_encoder(column_name)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1DeleteFileResponse,
                    parse_obj_as(
                        type_=V1DeleteFileResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get_file_scan_status(
        self,
        vault_id: str,
        table_name: str,
        id: str,
        column_name: str,
        *,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> V1GetFileScanStatusResponse:
        """
        Returns the anti-virus scan status of a file.

        Parameters
        ----------
        vault_id : str
            ID of the vault.

        table_name : str
            Name of the table.

        id : str
            `skyflow_id` of the record.

        column_name : str
            Name of the column that contains the file.

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

        Returns
        -------
        V1GetFileScanStatusResponse
            A successful response.

        Examples
        --------
        import asyncio

        from skyflow import AsyncSkyflow

        client = AsyncSkyflow(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.vault.get_file_scan_status(
                vault_id="vaultID",
                table_name="tableName",
                id="ID",
                column_name="columnName",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(table_name)}/{jsonable_encoder(id)}/files/{jsonable_encoder(column_name)}/scan-status",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    V1GetFileScanStatusResponse,
                    parse_obj_as(
                        type_=V1GetFileScanStatusResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        typing.Dict[str, typing.Optional[typing.Any]],
                        parse_obj_as(
                            type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
