diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6d78745..091cfb1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.9.0" + ".": "0.10.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 8601088..7e70f72 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/fragment-foundries-inc-dash%2Ffragment-0b499e34e128eee284c8b3d28d431f0521e747a9d573571b57b59c2dca2aac6e.yml -openapi_spec_hash: c50d64859d14067d66dc02c0da86184c -config_hash: 452389671401acf58c5429a09ae573db +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/fragment-foundries-inc-dash%2Ffragment-8472a9bd15eaa5b8aa9c12513d02b06ae385d06dd48e94a23f121678981de98a.yml +openapi_spec_hash: 4c42faa5ab6443bab546568adc330b7a +config_hash: 8e4b2d3ac55a0b2cdecfba99a1925e6f diff --git a/CHANGELOG.md b/CHANGELOG.md index ef5cf99..383e52e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.10.0 (2026-04-13) + +Full Changelog: [v0.9.0...v0.10.0](https://github.com/fragment-dev/fragment-py/compare/v0.9.0...v0.10.0) + +### Features + +* **api:** update SDK from prod (511af1bcd4001be60c589fed1d05a5814e416679) ([e2ce984](https://github.com/fragment-dev/fragment-py/commit/e2ce984d3cadaf39400d35ae5d35d464027dca54)) +* **api:** update SDK from prod (523b1fdd6cc6b5732ccdad5095c21f69fe1f7489) ([ea85617](https://github.com/fragment-dev/fragment-py/commit/ea85617c004e54e4a27abf4c8a5e585d17256d7c)) +* **api:** update SDK from prod (5cede0854eb141955854b7a9d3eb0e07a9588e3c) ([67481e4](https://github.com/fragment-dev/fragment-py/commit/67481e45971c9e704986c425b42b4a9938b45746)) +* **api:** update SDK from prod (729db28098a20ebc22e879a2cd1c6ad860f9ce4c) ([1d1b5d0](https://github.com/fragment-dev/fragment-py/commit/1d1b5d0b74975f2505475ca8167176680eff0655)) +* **api:** update SDK from prod (8051461980fb65468797d0b82dfa42dee9014004) ([25512da](https://github.com/fragment-dev/fragment-py/commit/25512da8089db4f3be50174a77373390fa29c52c)) +* **api:** update SDK from prod (a5eb093078fe5947a299bccafd30a0c7f2e90790) ([fc27b30](https://github.com/fragment-dev/fragment-py/commit/fc27b304c5dae27cb485853ad80c55b3c1392df0)) +* **api:** update SDK from prod (b3080493fb6bb118abdd03644b9ef6f59d417a3c) ([cd9337f](https://github.com/fragment-dev/fragment-py/commit/cd9337fbe43c0c5e6ed9ec1ef4c6db5bbf270403)) +* **api:** update SDK from prod (b8f6f1940acd3d10fc17aaeb59cd75281f3c6436) ([dca29fc](https://github.com/fragment-dev/fragment-py/commit/dca29fcd235fe6c110efcdf9042fe012d06ce17e)) +* **api:** update SDK from prod (d8f41b559592a1a8c68c0c40fdb773aa6e53795e) ([9bd565e](https://github.com/fragment-dev/fragment-py/commit/9bd565e3cee12d961291d7b4641195045097f7c9)) +* **api:** update SDK from prod (e1ebb9e4d62034855202a8ff99690880c072d953) ([4de3417](https://github.com/fragment-dev/fragment-py/commit/4de3417d2e14d337dc6bbd9f809c4bc6f624015b)) + + +### Bug Fixes + +* **client:** preserve hardcoded query params when merging with user params ([dd8e3f1](https://github.com/fragment-dev/fragment-py/commit/dd8e3f1966650b7cb4043f377c4fcf9b30e188ba)) +* ensure file data are only sent as 1 parameter ([b244d50](https://github.com/fragment-dev/fragment-py/commit/b244d5004f5f7fb0ba13745581e47e4bb84a67e4)) + ## 0.9.0 (2026-03-27) Full Changelog: [v0.8.0...v0.9.0](https://github.com/fragment-dev/fragment-py/compare/v0.8.0...v0.9.0) diff --git a/api.md b/api.md index f444e32..a140d9b 100644 --- a/api.md +++ b/api.md @@ -81,8 +81,8 @@ from fragment.types import ( Transaction, TransactionCreateResponse, TransactionRetrieveResponse, + TransactionUpdateResponse, TransactionListResponse, - TransactionCreateAllocationsResponse, TransactionListHistoryResponse, TransactionSearchResponse, TransactionSearchAllocationsResponse, @@ -93,8 +93,8 @@ Methods: - client.transactions.create(\*\*params) -> TransactionCreateResponse - client.transactions.retrieve(transaction_ref) -> TransactionRetrieveResponse +- client.transactions.update(transaction_ref, \*\*params) -> TransactionUpdateResponse - client.transactions.list(\*\*params) -> TransactionListResponse -- client.transactions.create_allocations(transaction_ref, \*\*params) -> TransactionCreateAllocationsResponse - client.transactions.list_history(transaction_ref) -> TransactionListHistoryResponse - client.transactions.search(\*\*params) -> TransactionSearchResponse - client.transactions.search_allocations(\*\*params) -> TransactionSearchAllocationsResponse diff --git a/pyproject.toml b/pyproject.toml index 06b2946..67a8a18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "fragment-py" -version = "0.9.0" +version = "0.10.0" description = "The official Python library for the fragment API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/fragment/_base_client.py b/src/fragment/_base_client.py index 57ac0fb..a78c425 100644 --- a/src/fragment/_base_client.py +++ b/src/fragment/_base_client.py @@ -540,6 +540,10 @@ def _build_request( files = cast(HttpxRequestFiles, ForceMultipartDict()) prepared_url = self._prepare_url(options.url) + # preserve hard-coded query params from the url + if params and prepared_url.query: + params = {**dict(prepared_url.params.items()), **params} + prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0]) if "_" in prepared_url.host: # work around https://github.com/encode/httpx/discussions/2880 kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")} diff --git a/src/fragment/_client.py b/src/fragment/_client.py index d91fcb0..a8932e4 100644 --- a/src/fragment/_client.py +++ b/src/fragment/_client.py @@ -113,6 +113,7 @@ def __init__( @cached_property def external_accounts(self) -> ExternalAccountsResource: + """External account management operations""" from .resources.external_accounts import ExternalAccountsResource return ExternalAccountsResource(self) @@ -147,6 +148,7 @@ def transactions(self) -> TransactionsResource: @cached_property def users(self) -> UsersResource: + """User management operations""" from .resources.users import UsersResource return UsersResource(self) @@ -342,6 +344,7 @@ def __init__( @cached_property def external_accounts(self) -> AsyncExternalAccountsResource: + """External account management operations""" from .resources.external_accounts import AsyncExternalAccountsResource return AsyncExternalAccountsResource(self) @@ -376,6 +379,7 @@ def transactions(self) -> AsyncTransactionsResource: @cached_property def users(self) -> AsyncUsersResource: + """User management operations""" from .resources.users import AsyncUsersResource return AsyncUsersResource(self) @@ -518,6 +522,7 @@ def __init__(self, client: Fragment) -> None: @cached_property def external_accounts(self) -> external_accounts.ExternalAccountsResourceWithRawResponse: + """External account management operations""" from .resources.external_accounts import ExternalAccountsResourceWithRawResponse return ExternalAccountsResourceWithRawResponse(self._client.external_accounts) @@ -552,6 +557,7 @@ def transactions(self) -> transactions.TransactionsResourceWithRawResponse: @cached_property def users(self) -> users.UsersResourceWithRawResponse: + """User management operations""" from .resources.users import UsersResourceWithRawResponse return UsersResourceWithRawResponse(self._client.users) @@ -565,6 +571,7 @@ def __init__(self, client: AsyncFragment) -> None: @cached_property def external_accounts(self) -> external_accounts.AsyncExternalAccountsResourceWithRawResponse: + """External account management operations""" from .resources.external_accounts import AsyncExternalAccountsResourceWithRawResponse return AsyncExternalAccountsResourceWithRawResponse(self._client.external_accounts) @@ -599,6 +606,7 @@ def transactions(self) -> transactions.AsyncTransactionsResourceWithRawResponse: @cached_property def users(self) -> users.AsyncUsersResourceWithRawResponse: + """User management operations""" from .resources.users import AsyncUsersResourceWithRawResponse return AsyncUsersResourceWithRawResponse(self._client.users) @@ -612,6 +620,7 @@ def __init__(self, client: Fragment) -> None: @cached_property def external_accounts(self) -> external_accounts.ExternalAccountsResourceWithStreamingResponse: + """External account management operations""" from .resources.external_accounts import ExternalAccountsResourceWithStreamingResponse return ExternalAccountsResourceWithStreamingResponse(self._client.external_accounts) @@ -646,6 +655,7 @@ def transactions(self) -> transactions.TransactionsResourceWithStreamingResponse @cached_property def users(self) -> users.UsersResourceWithStreamingResponse: + """User management operations""" from .resources.users import UsersResourceWithStreamingResponse return UsersResourceWithStreamingResponse(self._client.users) @@ -659,6 +669,7 @@ def __init__(self, client: AsyncFragment) -> None: @cached_property def external_accounts(self) -> external_accounts.AsyncExternalAccountsResourceWithStreamingResponse: + """External account management operations""" from .resources.external_accounts import AsyncExternalAccountsResourceWithStreamingResponse return AsyncExternalAccountsResourceWithStreamingResponse(self._client.external_accounts) @@ -693,6 +704,7 @@ def transactions(self) -> transactions.AsyncTransactionsResourceWithStreamingRes @cached_property def users(self) -> users.AsyncUsersResourceWithStreamingResponse: + """User management operations""" from .resources.users import AsyncUsersResourceWithStreamingResponse return AsyncUsersResourceWithStreamingResponse(self._client.users) diff --git a/src/fragment/_utils/_utils.py b/src/fragment/_utils/_utils.py index eec7f4a..63b8cd6 100644 --- a/src/fragment/_utils/_utils.py +++ b/src/fragment/_utils/_utils.py @@ -86,8 +86,9 @@ def _extract_items( index += 1 if is_dict(obj): try: - # We are at the last entry in the path so we must remove the field - if (len(path)) == index: + # Remove the field if there are no more dict keys in the path, + # only "" traversal markers or end. + if all(p == "" for p in path[index:]): item = obj.pop(key) else: item = obj[key] diff --git a/src/fragment/_version.py b/src/fragment/_version.py index f6d2ffa..bba4162 100644 --- a/src/fragment/_version.py +++ b/src/fragment/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "fragment" -__version__ = "0.9.0" # x-release-please-version +__version__ = "0.10.0" # x-release-please-version diff --git a/src/fragment/resources/external_accounts.py b/src/fragment/resources/external_accounts.py index 724c0af..0ff4275 100644 --- a/src/fragment/resources/external_accounts.py +++ b/src/fragment/resources/external_accounts.py @@ -23,6 +23,8 @@ class ExternalAccountsResource(SyncAPIResource): + """External account management operations""" + @cached_property def with_raw_response(self) -> ExternalAccountsResourceWithRawResponse: """ @@ -55,12 +57,12 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ExternalAccountCreateResponse: """ - Creates a new external account + Creates an external account. Args: - external_id: External ID for the account (user-provided, unique, mutable) + external_id: User-provided unique ID. - name: Human-readable name for the external account (mutable) + name: Name of the account. extra_headers: Send extra headers @@ -95,7 +97,7 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ExternalAccountListResponse: - """Lists all external accounts for the workspace""" + """Lists all external accounts.""" return self._get( "/external-accounts", options=make_request_options( @@ -106,6 +108,8 @@ def list( class AsyncExternalAccountsResource(AsyncAPIResource): + """External account management operations""" + @cached_property def with_raw_response(self) -> AsyncExternalAccountsResourceWithRawResponse: """ @@ -138,12 +142,12 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ExternalAccountCreateResponse: """ - Creates a new external account + Creates an external account. Args: - external_id: External ID for the account (user-provided, unique, mutable) + external_id: User-provided unique ID. - name: Human-readable name for the external account (mutable) + name: Name of the account. extra_headers: Send extra headers @@ -178,7 +182,7 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ExternalAccountListResponse: - """Lists all external accounts for the workspace""" + """Lists all external accounts.""" return await self._get( "/external-accounts", options=make_request_options( diff --git a/src/fragment/resources/invoices.py b/src/fragment/resources/invoices.py index 48b0387..4f6ea27 100644 --- a/src/fragment/resources/invoices.py +++ b/src/fragment/resources/invoices.py @@ -63,17 +63,15 @@ def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceCreateResponse: - """Creates a new invoice + """ + Creates an invoice. Args: - invoice_id: Unique identifier for the invoice. - - Make this the canonical ID from your system - for the transaction. + invoice_id: Unique ID for the invoice. - line_items: List of line items to create with the invoice + line_items: Line items to create with the invoice. - tags: Optional metadata tags for this invoice + tags: Tags for the invoice. extra_headers: Send extra headers @@ -111,10 +109,10 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceRetrieveResponse: """ - Gets an invoice by ID with balance details + Retrieves an invoice. Args: - id: Invoice ID + id: Unique identifier for the invoice. extra_headers: Send extra headers @@ -149,13 +147,16 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceUpdateResponse: """ - Updates an invoice + Updates an invoice. Args: - id: Invoice ID + id: Unique identifier for the invoice. + + current_invoice_version: Current version of the invoice. Must match the stored version. + + line_items: Line item updates. - current_invoice_version: The current version of the invoice. Must match the stored version for the update - to succeed (optimistic concurrency). + tags: Tag updates. extra_headers: Send extra headers @@ -193,7 +194,7 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceListResponse: - """Lists all invoices for the workspace""" + """Lists all invoices.""" return self._get( "/invoices", options=make_request_options( @@ -214,10 +215,10 @@ def list_history( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceListHistoryResponse: """ - Gets the version history of an invoice + Retrieves the version history of an invoice. Args: - id: Invoice ID + id: Unique identifier for the invoice. extra_headers: Send extra headers @@ -241,7 +242,7 @@ def search( self, *, filter: invoice_search_params.Filter, - page_info: invoice_search_params.PageInfo, + page_info: invoice_search_params.PageInfo | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -250,12 +251,12 @@ def search( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceSearchResponse: """ - Searches invoices + Searches invoices. Args: - filter: Filter criteria for the search + filter: Filter criteria for the search. - page_info: Pagination parameters + page_info: Pagination parameters. extra_headers: Send extra headers @@ -316,17 +317,15 @@ async def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceCreateResponse: - """Creates a new invoice + """ + Creates an invoice. Args: - invoice_id: Unique identifier for the invoice. - - Make this the canonical ID from your system - for the transaction. + invoice_id: Unique ID for the invoice. - line_items: List of line items to create with the invoice + line_items: Line items to create with the invoice. - tags: Optional metadata tags for this invoice + tags: Tags for the invoice. extra_headers: Send extra headers @@ -364,10 +363,10 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceRetrieveResponse: """ - Gets an invoice by ID with balance details + Retrieves an invoice. Args: - id: Invoice ID + id: Unique identifier for the invoice. extra_headers: Send extra headers @@ -402,13 +401,16 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceUpdateResponse: """ - Updates an invoice + Updates an invoice. Args: - id: Invoice ID + id: Unique identifier for the invoice. + + current_invoice_version: Current version of the invoice. Must match the stored version. + + line_items: Line item updates. - current_invoice_version: The current version of the invoice. Must match the stored version for the update - to succeed (optimistic concurrency). + tags: Tag updates. extra_headers: Send extra headers @@ -446,7 +448,7 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceListResponse: - """Lists all invoices for the workspace""" + """Lists all invoices.""" return await self._get( "/invoices", options=make_request_options( @@ -467,10 +469,10 @@ async def list_history( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceListHistoryResponse: """ - Gets the version history of an invoice + Retrieves the version history of an invoice. Args: - id: Invoice ID + id: Unique identifier for the invoice. extra_headers: Send extra headers @@ -494,7 +496,7 @@ async def search( self, *, filter: invoice_search_params.Filter, - page_info: invoice_search_params.PageInfo, + page_info: invoice_search_params.PageInfo | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -503,12 +505,12 @@ async def search( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InvoiceSearchResponse: """ - Searches invoices + Searches invoices. Args: - filter: Filter criteria for the search + filter: Filter criteria for the search. - page_info: Pagination parameters + page_info: Pagination parameters. extra_headers: Send extra headers diff --git a/src/fragment/resources/products.py b/src/fragment/resources/products.py index 665b13f..00147d5 100644 --- a/src/fragment/resources/products.py +++ b/src/fragment/resources/products.py @@ -62,18 +62,18 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProductCreateResponse: """ - Creates a new product + Creates a product. Args: - code: Product code (unique identifier) + code: Unique product code. - description: Description of the product + description: Product description. - paid_by_roles: Roles that can pay for this product. Reference roles by id or name. At least one - of paid_by_roles or paid_to_roles must be provided. + paid_by_roles: Roles that can pay for the product. Reference roles by `id` or `name`. At least + one of `paid_by_roles` or `paid_to_roles` must be provided. - paid_to_roles: Roles that receive payment for this product. Reference roles by id or name. At - least one of paid_by_roles or paid_to_roles must be provided. + paid_to_roles: Roles that can receive payment for the product. Reference roles by `id` or + `name`. At least one of `paid_by_roles` or `paid_to_roles` must be provided. extra_headers: Send extra headers @@ -111,11 +111,12 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProductRetrieveResponse: - """ - Gets a product by code + """Retrieves a product by code. Args: - code: Product code + code: Product code. + + Must not include #, /, or :. extra_headers: Send extra headers @@ -145,7 +146,7 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProductListResponse: - """Lists all products for the workspace""" + """Lists all products.""" return self._get( "/products", options=make_request_options( @@ -192,18 +193,18 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProductCreateResponse: """ - Creates a new product + Creates a product. Args: - code: Product code (unique identifier) + code: Unique product code. - description: Description of the product + description: Product description. - paid_by_roles: Roles that can pay for this product. Reference roles by id or name. At least one - of paid_by_roles or paid_to_roles must be provided. + paid_by_roles: Roles that can pay for the product. Reference roles by `id` or `name`. At least + one of `paid_by_roles` or `paid_to_roles` must be provided. - paid_to_roles: Roles that receive payment for this product. Reference roles by id or name. At - least one of paid_by_roles or paid_to_roles must be provided. + paid_to_roles: Roles that can receive payment for the product. Reference roles by `id` or + `name`. At least one of `paid_by_roles` or `paid_to_roles` must be provided. extra_headers: Send extra headers @@ -241,11 +242,12 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProductRetrieveResponse: - """ - Gets a product by code + """Retrieves a product by code. Args: - code: Product code + code: Product code. + + Must not include #, /, or :. extra_headers: Send extra headers @@ -275,7 +277,7 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ProductListResponse: - """Lists all products for the workspace""" + """Lists all products.""" return await self._get( "/products", options=make_request_options( diff --git a/src/fragment/resources/roles.py b/src/fragment/resources/roles.py index 8fb673d..ee4729e 100644 --- a/src/fragment/resources/roles.py +++ b/src/fragment/resources/roles.py @@ -56,10 +56,10 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RoleCreateResponse: """ - Creates a new role + Creates a role. Args: - role: Name of the role + role: Name of the role. extra_headers: Send extra headers @@ -88,7 +88,7 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RoleListResponse: - """Lists all roles for the workspace""" + """Lists all roles.""" return self._get( "/roles", options=make_request_options( @@ -132,10 +132,10 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RoleCreateResponse: """ - Creates a new role + Creates a role. Args: - role: Name of the role + role: Name of the role. extra_headers: Send extra headers @@ -164,7 +164,7 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> RoleListResponse: - """Lists all roles for the workspace""" + """Lists all roles.""" return await self._get( "/roles", options=make_request_options( diff --git a/src/fragment/resources/transactions.py b/src/fragment/resources/transactions.py index 673bbe9..b8b30a4 100644 --- a/src/fragment/resources/transactions.py +++ b/src/fragment/resources/transactions.py @@ -12,7 +12,7 @@ transaction_list_params, transaction_create_params, transaction_search_params, - transaction_create_allocations_params, + transaction_update_params, transaction_search_allocations_params, ) from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given @@ -29,9 +29,9 @@ from ..types.transaction_list_response import TransactionListResponse from ..types.transaction_create_response import TransactionCreateResponse from ..types.transaction_search_response import TransactionSearchResponse +from ..types.transaction_update_response import TransactionUpdateResponse from ..types.transaction_retrieve_response import TransactionRetrieveResponse from ..types.transaction_list_history_response import TransactionListHistoryResponse -from ..types.transaction_create_allocations_response import TransactionCreateAllocationsResponse from ..types.transaction_search_allocations_response import TransactionSearchAllocationsResponse __all__ = ["TransactionsResource", "AsyncTransactionsResource"] @@ -256,24 +256,26 @@ def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionCreateResponse: - """ - Syncs a transaction, optionally with allocations + """Creates a transaction. Args: - account: Account reference. Provide id, external_id, or both. + account: External account for the transaction. + + Identify it by `id`, `external_id`, or + both. - allocations: Allocation entries for this transaction. Empty indicates unreconciled funds. + allocations: Allocations for the transaction. An empty array indicates unreconciled funds. - amount: Amount in smallest currency unit as stringified bigint (can be positive or - negative). + amount: Transaction amount, as a string in the smallest currency unit, such as cents for + USD. Can be positive or negative. - currency: Currency code (ISO 4217 or crypto) + currency: ISO 4217 or crypto currency code. - external_id: External transaction ID used for idempotent sync. + external_id: User-provided unique ID. - posted: Posted timestamp in ISO 8601 format. + posted: Timestamp when the transaction was posted. Uses ISO 8601 format. - tags: Optional metadata tags for this transaction + tags: Tags for the transaction. extra_headers: Send extra headers @@ -315,11 +317,10 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionRetrieveResponse: """ - Gets a transaction by ID or external ID + Retrieves a transaction by ID or external ID. Args: - transaction_ref: Transaction reference. Accepts either an encoded Fragment ID (txn_xxx) or an - external ID. + transaction_ref: Transaction `id` or `external_id`. extra_headers: Send extra headers @@ -339,28 +340,31 @@ def retrieve( cast_to=TransactionRetrieveResponse, ) - def list( + def update( self, + transaction_ref: str, *, - account: str | Omit = omit, - reconciliation_status: Literal["reconciled", "unreconciled"] | Omit = omit, + current_transaction_version: int, + allocations: transaction_update_params.Allocations | Omit = omit, + tags: transaction_update_params.Tags | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TransactionListResponse: - """Lists all transactions for the workspace + ) -> TransactionUpdateResponse: + """ + Updates a transaction. Args: - account: Filter by account. + transaction_ref: Transaction `id` or `external_id`. + + current_transaction_version: Current version of the transaction. Must match the stored version. - Encoded account ID (ext_account_xxx) or external_id. If the - account does not exist, returns an empty list. + allocations: Allocation updates. - reconciliation_status: Filter by reconciliation state. reconciled = unallocated_amount === 0; - unreconciled = unallocated_amount !== 0. Omit for all transactions. + tags: Tag updates. extra_headers: Send extra headers @@ -370,47 +374,46 @@ def list( timeout: Override the client-level default timeout for this request, in seconds """ - return self._get( - "/transactions", + if not transaction_ref: + raise ValueError(f"Expected a non-empty value for `transaction_ref` but received {transaction_ref!r}") + return self._patch( + path_template("/transactions/{transaction_ref}", transaction_ref=transaction_ref), + body=maybe_transform( + { + "current_transaction_version": current_transaction_version, + "allocations": allocations, + "tags": tags, + }, + transaction_update_params.TransactionUpdateParams, + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "account": account, - "reconciliation_status": reconciliation_status, - }, - transaction_list_params.TransactionListParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TransactionListResponse, + cast_to=TransactionUpdateResponse, ) - def create_allocations( + def list( self, - transaction_ref: str, *, - allocation_updates: Iterable[transaction_create_allocations_params.AllocationUpdate], - version: int, + account: str | Omit = omit, + reconciliation_status: Literal["reconciled", "unreconciled"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TransactionCreateAllocationsResponse: + ) -> TransactionListResponse: """ - Updates allocations on an existing transaction + Lists all transactions. Args: - transaction_ref: Transaction reference. Accepts either an encoded Fragment ID (txn_xxx) or an - external ID. + account: Filter by account `id` or `external_id`. If the account does not exist, returns + an empty list. - allocation_updates: Allocation operations to apply - - version: Current transaction version for optimistic concurrency control + reconciliation_status: Filter by reconciliation status. `reconciled` returns transactions where + unallocated_amount is 0. `unreconciled` returns transactions where + unallocated_amount is not 0. Omit for all transactions. extra_headers: Send extra headers @@ -420,21 +423,22 @@ def create_allocations( timeout: Override the client-level default timeout for this request, in seconds """ - if not transaction_ref: - raise ValueError(f"Expected a non-empty value for `transaction_ref` but received {transaction_ref!r}") - return self._post( - path_template("/transactions/{transaction_ref}/allocations", transaction_ref=transaction_ref), - body=maybe_transform( - { - "allocation_updates": allocation_updates, - "version": version, - }, - transaction_create_allocations_params.TransactionCreateAllocationsParams, - ), + return self._get( + "/transactions", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "account": account, + "reconciliation_status": reconciliation_status, + }, + transaction_list_params.TransactionListParams, + ), ), - cast_to=TransactionCreateAllocationsResponse, + cast_to=TransactionListResponse, ) def list_history( @@ -449,11 +453,10 @@ def list_history( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionListHistoryResponse: """ - Gets the version history of a transaction + Retrieves the version history of a transaction. Args: - transaction_ref: Transaction reference. Accepts either an encoded Fragment ID (txn_xxx) or an - external ID. + transaction_ref: Transaction `id` or `external_id`. extra_headers: Send extra headers @@ -477,6 +480,7 @@ def search( self, *, filter: transaction_search_params.Filter, + page_info: transaction_search_params.PageInfo | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -485,10 +489,12 @@ def search( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionSearchResponse: """ - Searches transactions by filter criteria + Searches transactions. Args: - filter: Filter criteria for searching transactions. + filter: Filter for searching transactions. + + page_info: Pagination parameters. extra_headers: Send extra headers @@ -500,7 +506,13 @@ def search( """ return self._post( "/transactions/search", - body=maybe_transform({"filter": filter}, transaction_search_params.TransactionSearchParams), + body=maybe_transform( + { + "filter": filter, + "page_info": page_info, + }, + transaction_search_params.TransactionSearchParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -519,10 +531,10 @@ def search_allocations( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionSearchAllocationsResponse: """ - Searches transaction allocations by filter criteria + Searches transaction allocations. Args: - filter: Filter criteria for searching transaction allocations. + filter: Filter for searching transaction allocations. extra_headers: Send extra headers @@ -763,24 +775,26 @@ async def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionCreateResponse: - """ - Syncs a transaction, optionally with allocations + """Creates a transaction. Args: - account: Account reference. Provide id, external_id, or both. + account: External account for the transaction. + + Identify it by `id`, `external_id`, or + both. - allocations: Allocation entries for this transaction. Empty indicates unreconciled funds. + allocations: Allocations for the transaction. An empty array indicates unreconciled funds. - amount: Amount in smallest currency unit as stringified bigint (can be positive or - negative). + amount: Transaction amount, as a string in the smallest currency unit, such as cents for + USD. Can be positive or negative. - currency: Currency code (ISO 4217 or crypto) + currency: ISO 4217 or crypto currency code. - external_id: External transaction ID used for idempotent sync. + external_id: User-provided unique ID. - posted: Posted timestamp in ISO 8601 format. + posted: Timestamp when the transaction was posted. Uses ISO 8601 format. - tags: Optional metadata tags for this transaction + tags: Tags for the transaction. extra_headers: Send extra headers @@ -822,11 +836,10 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionRetrieveResponse: """ - Gets a transaction by ID or external ID + Retrieves a transaction by ID or external ID. Args: - transaction_ref: Transaction reference. Accepts either an encoded Fragment ID (txn_xxx) or an - external ID. + transaction_ref: Transaction `id` or `external_id`. extra_headers: Send extra headers @@ -846,28 +859,31 @@ async def retrieve( cast_to=TransactionRetrieveResponse, ) - async def list( + async def update( self, + transaction_ref: str, *, - account: str | Omit = omit, - reconciliation_status: Literal["reconciled", "unreconciled"] | Omit = omit, + current_transaction_version: int, + allocations: transaction_update_params.Allocations | Omit = omit, + tags: transaction_update_params.Tags | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TransactionListResponse: - """Lists all transactions for the workspace + ) -> TransactionUpdateResponse: + """ + Updates a transaction. Args: - account: Filter by account. + transaction_ref: Transaction `id` or `external_id`. + + current_transaction_version: Current version of the transaction. Must match the stored version. - Encoded account ID (ext_account_xxx) or external_id. If the - account does not exist, returns an empty list. + allocations: Allocation updates. - reconciliation_status: Filter by reconciliation state. reconciled = unallocated_amount === 0; - unreconciled = unallocated_amount !== 0. Omit for all transactions. + tags: Tag updates. extra_headers: Send extra headers @@ -877,47 +893,46 @@ async def list( timeout: Override the client-level default timeout for this request, in seconds """ - return await self._get( - "/transactions", + if not transaction_ref: + raise ValueError(f"Expected a non-empty value for `transaction_ref` but received {transaction_ref!r}") + return await self._patch( + path_template("/transactions/{transaction_ref}", transaction_ref=transaction_ref), + body=await async_maybe_transform( + { + "current_transaction_version": current_transaction_version, + "allocations": allocations, + "tags": tags, + }, + transaction_update_params.TransactionUpdateParams, + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "account": account, - "reconciliation_status": reconciliation_status, - }, - transaction_list_params.TransactionListParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TransactionListResponse, + cast_to=TransactionUpdateResponse, ) - async def create_allocations( + async def list( self, - transaction_ref: str, *, - allocation_updates: Iterable[transaction_create_allocations_params.AllocationUpdate], - version: int, + account: str | Omit = omit, + reconciliation_status: Literal["reconciled", "unreconciled"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TransactionCreateAllocationsResponse: + ) -> TransactionListResponse: """ - Updates allocations on an existing transaction + Lists all transactions. Args: - transaction_ref: Transaction reference. Accepts either an encoded Fragment ID (txn_xxx) or an - external ID. - - allocation_updates: Allocation operations to apply + account: Filter by account `id` or `external_id`. If the account does not exist, returns + an empty list. - version: Current transaction version for optimistic concurrency control + reconciliation_status: Filter by reconciliation status. `reconciled` returns transactions where + unallocated_amount is 0. `unreconciled` returns transactions where + unallocated_amount is not 0. Omit for all transactions. extra_headers: Send extra headers @@ -927,21 +942,22 @@ async def create_allocations( timeout: Override the client-level default timeout for this request, in seconds """ - if not transaction_ref: - raise ValueError(f"Expected a non-empty value for `transaction_ref` but received {transaction_ref!r}") - return await self._post( - path_template("/transactions/{transaction_ref}/allocations", transaction_ref=transaction_ref), - body=await async_maybe_transform( - { - "allocation_updates": allocation_updates, - "version": version, - }, - transaction_create_allocations_params.TransactionCreateAllocationsParams, - ), + return await self._get( + "/transactions", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "account": account, + "reconciliation_status": reconciliation_status, + }, + transaction_list_params.TransactionListParams, + ), ), - cast_to=TransactionCreateAllocationsResponse, + cast_to=TransactionListResponse, ) async def list_history( @@ -956,11 +972,10 @@ async def list_history( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionListHistoryResponse: """ - Gets the version history of a transaction + Retrieves the version history of a transaction. Args: - transaction_ref: Transaction reference. Accepts either an encoded Fragment ID (txn_xxx) or an - external ID. + transaction_ref: Transaction `id` or `external_id`. extra_headers: Send extra headers @@ -984,6 +999,7 @@ async def search( self, *, filter: transaction_search_params.Filter, + page_info: transaction_search_params.PageInfo | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -992,10 +1008,12 @@ async def search( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionSearchResponse: """ - Searches transactions by filter criteria + Searches transactions. Args: - filter: Filter criteria for searching transactions. + filter: Filter for searching transactions. + + page_info: Pagination parameters. extra_headers: Send extra headers @@ -1007,7 +1025,13 @@ async def search( """ return await self._post( "/transactions/search", - body=await async_maybe_transform({"filter": filter}, transaction_search_params.TransactionSearchParams), + body=await async_maybe_transform( + { + "filter": filter, + "page_info": page_info, + }, + transaction_search_params.TransactionSearchParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -1026,10 +1050,10 @@ async def search_allocations( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TransactionSearchAllocationsResponse: """ - Searches transaction allocations by filter criteria + Searches transaction allocations. Args: - filter: Filter criteria for searching transaction allocations. + filter: Filter for searching transaction allocations. extra_headers: Send extra headers @@ -1061,12 +1085,12 @@ def __init__(self, transactions: TransactionsResource) -> None: self.retrieve = to_raw_response_wrapper( transactions.retrieve, ) + self.update = to_raw_response_wrapper( + transactions.update, + ) self.list = to_raw_response_wrapper( transactions.list, ) - self.create_allocations = to_raw_response_wrapper( - transactions.create_allocations, - ) self.list_history = to_raw_response_wrapper( transactions.list_history, ) @@ -1088,12 +1112,12 @@ def __init__(self, transactions: AsyncTransactionsResource) -> None: self.retrieve = async_to_raw_response_wrapper( transactions.retrieve, ) + self.update = async_to_raw_response_wrapper( + transactions.update, + ) self.list = async_to_raw_response_wrapper( transactions.list, ) - self.create_allocations = async_to_raw_response_wrapper( - transactions.create_allocations, - ) self.list_history = async_to_raw_response_wrapper( transactions.list_history, ) @@ -1115,12 +1139,12 @@ def __init__(self, transactions: TransactionsResource) -> None: self.retrieve = to_streamed_response_wrapper( transactions.retrieve, ) + self.update = to_streamed_response_wrapper( + transactions.update, + ) self.list = to_streamed_response_wrapper( transactions.list, ) - self.create_allocations = to_streamed_response_wrapper( - transactions.create_allocations, - ) self.list_history = to_streamed_response_wrapper( transactions.list_history, ) @@ -1142,12 +1166,12 @@ def __init__(self, transactions: AsyncTransactionsResource) -> None: self.retrieve = async_to_streamed_response_wrapper( transactions.retrieve, ) + self.update = async_to_streamed_response_wrapper( + transactions.update, + ) self.list = async_to_streamed_response_wrapper( transactions.list, ) - self.create_allocations = async_to_streamed_response_wrapper( - transactions.create_allocations, - ) self.list_history = async_to_streamed_response_wrapper( transactions.list_history, ) diff --git a/src/fragment/resources/users.py b/src/fragment/resources/users.py index d37e0eb..7994af1 100644 --- a/src/fragment/resources/users.py +++ b/src/fragment/resources/users.py @@ -23,6 +23,8 @@ class UsersResource(SyncAPIResource): + """User management operations""" + @cached_property def with_raw_response(self) -> UsersResourceWithRawResponse: """ @@ -55,12 +57,12 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> UserCreateResponse: """ - Creates a new user + Creates a user. Args: - external_id: External ID for the user + external_id: User-provided unique ID. - role: Role of the user + role: Name of the role to assign. Must match an existing role. extra_headers: Send extra headers @@ -95,7 +97,7 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> UserListResponse: - """Lists all users for the workspace""" + """Lists all users.""" return self._get( "/users", options=make_request_options( @@ -106,6 +108,8 @@ def list( class AsyncUsersResource(AsyncAPIResource): + """User management operations""" + @cached_property def with_raw_response(self) -> AsyncUsersResourceWithRawResponse: """ @@ -138,12 +142,12 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> UserCreateResponse: """ - Creates a new user + Creates a user. Args: - external_id: External ID for the user + external_id: User-provided unique ID. - role: Role of the user + role: Name of the role to assign. Must match an existing role. extra_headers: Send extra headers @@ -178,7 +182,7 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> UserListResponse: - """Lists all users for the workspace""" + """Lists all users.""" return await self._get( "/users", options=make_request_options( diff --git a/src/fragment/types/__init__.py b/src/fragment/types/__init__.py index 5f5dbd0..290f576 100644 --- a/src/fragment/types/__init__.py +++ b/src/fragment/types/__init__.py @@ -30,23 +30,19 @@ from .transaction_create_params import TransactionCreateParams as TransactionCreateParams from .transaction_list_response import TransactionListResponse as TransactionListResponse from .transaction_search_params import TransactionSearchParams as TransactionSearchParams +from .transaction_update_params import TransactionUpdateParams as TransactionUpdateParams from .transaction_create_response import TransactionCreateResponse as TransactionCreateResponse from .transaction_search_response import TransactionSearchResponse as TransactionSearchResponse +from .transaction_update_response import TransactionUpdateResponse as TransactionUpdateResponse from .invoice_list_history_response import InvoiceListHistoryResponse as InvoiceListHistoryResponse from .transaction_retrieve_response import TransactionRetrieveResponse as TransactionRetrieveResponse from .external_account_create_params import ExternalAccountCreateParams as ExternalAccountCreateParams from .external_account_list_response import ExternalAccountListResponse as ExternalAccountListResponse from .external_account_create_response import ExternalAccountCreateResponse as ExternalAccountCreateResponse from .transaction_list_history_response import TransactionListHistoryResponse as TransactionListHistoryResponse -from .transaction_create_allocations_params import ( - TransactionCreateAllocationsParams as TransactionCreateAllocationsParams, -) from .transaction_search_allocations_params import ( TransactionSearchAllocationsParams as TransactionSearchAllocationsParams, ) -from .transaction_create_allocations_response import ( - TransactionCreateAllocationsResponse as TransactionCreateAllocationsResponse, -) from .transaction_search_allocations_response import ( TransactionSearchAllocationsResponse as TransactionSearchAllocationsResponse, ) diff --git a/src/fragment/types/external_account.py b/src/fragment/types/external_account.py index 2129b3d..02f2920 100644 --- a/src/fragment/types/external_account.py +++ b/src/fragment/types/external_account.py @@ -6,13 +6,13 @@ class ExternalAccount(BaseModel): - """External account object""" + """External account object.""" id: str - """Fragment-generated unique ID for the external account""" + """FRAGMENT generated unique ID.""" external_id: str - """User-provided external ID""" + """User-provided unique ID.""" name: str - """Human-readable name for the external account""" + """Name of the account.""" diff --git a/src/fragment/types/external_account_create_params.py b/src/fragment/types/external_account_create_params.py index e4113a5..ee8aaa3 100644 --- a/src/fragment/types/external_account_create_params.py +++ b/src/fragment/types/external_account_create_params.py @@ -9,7 +9,7 @@ class ExternalAccountCreateParams(TypedDict, total=False): external_id: Required[str] - """External ID for the account (user-provided, unique, mutable)""" + """User-provided unique ID.""" name: Required[str] - """Human-readable name for the external account (mutable)""" + """Name of the account.""" diff --git a/src/fragment/types/external_account_create_response.py b/src/fragment/types/external_account_create_response.py index ee0c3ec..9062890 100644 --- a/src/fragment/types/external_account_create_response.py +++ b/src/fragment/types/external_account_create_response.py @@ -8,4 +8,4 @@ class ExternalAccountCreateResponse(BaseModel): data: ExternalAccount - """External account object""" + """External account object.""" diff --git a/src/fragment/types/external_account_list_response.py b/src/fragment/types/external_account_list_response.py index fe69982..eb11ebd 100644 --- a/src/fragment/types/external_account_list_response.py +++ b/src/fragment/types/external_account_list_response.py @@ -9,6 +9,6 @@ class ExternalAccountListResponse(BaseModel): - """List of external accounts""" + """List of external accounts.""" data: List[ExternalAccount] diff --git a/src/fragment/types/invoice.py b/src/fragment/types/invoice.py index 57bbe8f..0d994a9 100644 --- a/src/fragment/types/invoice.py +++ b/src/fragment/types/invoice.py @@ -10,48 +10,48 @@ class Tag(BaseModel): - """A key-value tag pair""" + """A key-value tag pair.""" key: str - """Tag key""" + """Tag key.""" value: str - """Tag value""" + """Tag value.""" class LineItemPrice(BaseModel): - """Price breakdown containing amount, unit price, and quantity""" + """Price breakdown.""" amount: str - """Total amount in smallest currency unit (represented as string for bigint)""" + """Total amount as a string in the smallest currency unit, such as cents for USD.""" quantity: int - """Quantity of units for this line item""" + """Number of units.""" unit_price: str - """Unit price in smallest currency unit (represented as string for bigint)""" + """Unit price as a string in the smallest currency unit, such as cents for USD.""" class LineItemTag(BaseModel): - """A key-value tag pair""" + """A key-value tag pair.""" key: str - """Tag key""" + """Tag key.""" value: str - """Tag value""" + """Tag value.""" class LineItem(BaseModel): - """Invoice line item object""" + """Invoice line item.""" id: str - """Unique identifier for the line item""" + """FRAGMENT generated unique ID.""" amount: str - """Deprecated: use price.amount instead. + """Total amount as a string in the smallest currency unit, such as cents for USD. - Total amount in smallest currency unit (represented as string for bigint) + Deprecated, use price.amount instead. """ currency_code: Literal[ @@ -235,53 +235,50 @@ class LineItem(BaseModel): "LOGICAL", "CUSTOM", ] - """Currency code (ISO 4217 or crypto)""" + """ISO 4217 or crypto currency code.""" description: str - """Description of the line item""" + """Description of the line item.""" price: LineItemPrice - """Price breakdown containing amount, unit price, and quantity""" + """Price breakdown.""" product_id: str - """ID of the product/catalog item""" + """Unique identifier for the product.""" tags: List[LineItemTag] - """Metadata tags for this line item""" + """Tags for the line item.""" type: Literal["payin", "payout"] - """The type of the line item""" + """Type of the line item.""" user_id: str - """External ID of the user associated with this line item""" + """User-provided unique external ID.""" class Invoice(BaseModel): - """Invoice object""" + """Invoice object.""" id: str - """Unique identifier for the invoice""" + """Unique invoice ID.""" created: datetime - """ISO 8601 timestamp when the invoice was created""" + """Timestamp when the invoice was created. Uses ISO 8601 format.""" status: Literal["active"] - """The status of the invoice""" + """Status of the invoice. Deprecated.""" tags: List[Tag] - """Metadata tags for this invoice""" + """Tags for the invoice.""" version: float - """The current version of the invoice. - - Pass this value when updating to ensure thread safety. - """ + """Current version of the invoice.""" workspace_id: str - """Workspace ID this invoice belongs to""" + """Workspace the invoice belongs to.""" line_items: Optional[List[LineItem]] = None - """List of line items associated with this invoice""" + """Line items for the invoice.""" modified: Optional[datetime] = None - """ISO 8601 timestamp when the invoice was last modified""" + """Timestamp when the invoice was last modified. Uses ISO 8601 format.""" diff --git a/src/fragment/types/invoice_create_params.py b/src/fragment/types/invoice_create_params.py index 13fbb5a..33a09b3 100644 --- a/src/fragment/types/invoice_create_params.py +++ b/src/fragment/types/invoice_create_params.py @@ -19,82 +19,76 @@ class InvoiceCreateParams(TypedDict, total=False): invoice_id: Required[str] - """Unique identifier for the invoice. - - Make this the canonical ID from your system for the transaction. - """ + """Unique ID for the invoice.""" line_items: Required[Iterable[LineItem]] - """List of line items to create with the invoice""" + """Line items to create with the invoice.""" tags: Iterable[Tag] - """Optional metadata tags for this invoice""" + """Tags for the invoice.""" class LineItemUserID(TypedDict, total=False): id: Required[str] - """FRAGMENT generated ID of the user""" + """FRAGMENT generated unique ID.""" class LineItemUserExternalID(TypedDict, total=False): external_id: Required[str] - """External ID of the user""" + """User-provided unique ID.""" LineItemUser: TypeAlias = Union[LineItemUserID, LineItemUserExternalID] class LineItemPrice(TypedDict, total=False): - """Price breakdown. Provide amount, or unit_price + quantity, or all three.""" + """Price breakdown. Provide amount, or unit_price and quantity, or all three.""" amount: str - """Total amount in smallest currency unit. + """Total amount as a string in the smallest currency unit, such as cents for USD. Required if unit_price and quantity are not provided. """ quantity: int - """Number of units for this line item.""" + """Number of units for the line item.""" unit_price: str - """Price per unit in smallest currency unit.""" + """ + Price per unit as a string in the smallest currency unit, such as cents for USD. + """ class LineItemTag(TypedDict, total=False): - """A key-value tag pair for metadata""" + """A key-value tag pair for metadata.""" key: Required[str] - """Tag key. - - Must be a valid safe string (no special characters like #, /, :). Max 50 - characters. - """ + """Tag key. Must not contain #, /, or :. Max 50 characters.""" value: Required[str] - """Tag value. - - Must be a valid safe string (no special characters like #, /, :). Max 200 - characters. - """ + """Tag value. Must not contain #, /, or :. Max 200 characters.""" class LineItem(TypedDict, total=False): """Data to create a line item.""" description: Required[str] - """Description of the line item""" + """Description of the line item.""" product_id: Required[str] - """ID of the product/catalog item""" + """Unique identifier for the product.""" type: Required[Literal["payin", "payout"]] - """The type of the line item""" + """Type of the line item.""" user: Required[LineItemUser] - """Identifies a user by Fragment-generated id or external_id (request body).""" + """Identifies a user by `id` or `external_id`.""" amount: str - """Deprecated: use price instead. Total amount in smallest currency unit.""" + """Total amount as a string in the smallest currency unit, such as cents for USD. + + Deprecated, use price instead. + """ currency_code: Literal[ "ADA", @@ -277,28 +271,20 @@ class LineItem(TypedDict, total=False): "LOGICAL", "CUSTOM", ] - """Currency code (ISO 4217 or crypto)""" + """ISO 4217 or crypto currency code.""" price: LineItemPrice - """Price breakdown. Provide amount, or unit_price + quantity, or all three.""" + """Price breakdown. Provide amount, or unit_price and quantity, or all three.""" tags: Iterable[LineItemTag] - """Optional metadata tags for this line item""" + """Tags for the line item.""" class Tag(TypedDict, total=False): - """A key-value tag pair for metadata""" + """A key-value tag pair for metadata.""" key: Required[str] - """Tag key. - - Must be a valid safe string (no special characters like #, /, :). Max 50 - characters. - """ + """Tag key. Must not contain #, /, or :. Max 50 characters.""" value: Required[str] - """Tag value. - - Must be a valid safe string (no special characters like #, /, :). Max 200 - characters. - """ + """Tag value. Must not contain #, /, or :. Max 200 characters.""" diff --git a/src/fragment/types/invoice_create_response.py b/src/fragment/types/invoice_create_response.py index eec755f..0199cce 100644 --- a/src/fragment/types/invoice_create_response.py +++ b/src/fragment/types/invoice_create_response.py @@ -8,4 +8,4 @@ class InvoiceCreateResponse(BaseModel): data: Invoice - """Invoice object""" + """Invoice object.""" diff --git a/src/fragment/types/invoice_list_history_response.py b/src/fragment/types/invoice_list_history_response.py index ed3d106..af74d5b 100644 --- a/src/fragment/types/invoice_list_history_response.py +++ b/src/fragment/types/invoice_list_history_response.py @@ -1,579 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing import List from .invoice import Invoice from .._models import BaseModel -__all__ = [ - "InvoiceListHistoryResponse", - "Data", - "DataDiff", - "DataDiffAddDiffEntry", - "DataDiffAddDiffEntryItem", - "DataDiffAddDiffEntryItemPrice", - "DataDiffAddDiffEntryItemTag", - "DataDiffUpdateDiffEntry", - "DataDiffUpdateDiffEntryNewPrice", - "DataDiffUpdateDiffEntryOldPrice", - "DataDiffDeleteDiffEntry", - "DataDiffDeleteDiffEntryItem", - "DataDiffDeleteDiffEntryItemPrice", - "DataDiffDeleteDiffEntryItemTag", -] - - -class DataDiffAddDiffEntryItemPrice(BaseModel): - """Price breakdown containing amount, unit price, and quantity""" - - amount: str - """Total amount in smallest currency unit (represented as string for bigint)""" - - quantity: int - """Quantity of units for this line item""" - - unit_price: str - """Unit price in smallest currency unit (represented as string for bigint)""" - - -class DataDiffAddDiffEntryItemTag(BaseModel): - """A key-value tag pair""" - - key: str - """Tag key""" - - value: str - """Tag value""" - - -class DataDiffAddDiffEntryItem(BaseModel): - """Invoice line item object""" - - id: str - """Unique identifier for the line item""" - - amount: str - """Deprecated: use price.amount instead. - - Total amount in smallest currency unit (represented as string for bigint) - """ - - currency_code: Literal[ - "ADA", - "BTC", - "DAI", - "ETH", - "SOL", - "USDC", - "USDT", - "USDG", - "EURC", - "CADC", - "CADT", - "XLM", - "UNI", - "BCH", - "LTC", - "AAVE", - "LINK", - "MATIC", - "PTS", - "AED", - "AFN", - "ALL", - "AMD", - "ANG", - "AOA", - "ARS", - "AUD", - "AWG", - "AZN", - "BAM", - "BBD", - "BDT", - "BGN", - "BHD", - "BIF", - "BMD", - "BND", - "BOB", - "BRL", - "BSD", - "BTN", - "BWP", - "BYR", - "BZD", - "CAD", - "CDF", - "CHF", - "CLP", - "CNY", - "COP", - "CRC", - "CUC", - "CUP", - "CVE", - "CZK", - "DJF", - "DKK", - "DOP", - "DZD", - "EGP", - "ERN", - "ETB", - "EUR", - "FJD", - "FKP", - "GBP", - "GEL", - "GGP", - "GHS", - "GIP", - "GMD", - "GNF", - "GTQ", - "GYD", - "HKD", - "HNL", - "HRK", - "HTG", - "HUF", - "IDR", - "ILS", - "IMP", - "INR", - "IQD", - "IRR", - "ISK", - "JMD", - "JOD", - "JPY", - "KES", - "KGS", - "KHR", - "KMF", - "KPW", - "KRW", - "KWD", - "KYD", - "KZT", - "LAK", - "LBP", - "LKR", - "LRD", - "LSL", - "LYD", - "MAD", - "MDL", - "MGA", - "MKD", - "MMK", - "MNT", - "MOP", - "MUR", - "MVR", - "MWK", - "MXN", - "MYR", - "MZN", - "NAD", - "NGN", - "NIO", - "NOK", - "NPR", - "NZD", - "OMR", - "PAB", - "PEN", - "PGK", - "PHP", - "PKR", - "PLN", - "PYG", - "QAR", - "RON", - "RSD", - "RUB", - "RWF", - "SAR", - "SBD", - "SCR", - "SDG", - "SEK", - "SGD", - "SHP", - "SLL", - "SOS", - "SPL", - "SRD", - "SVC", - "SYP", - "STN", - "SZL", - "THB", - "TJS", - "TMT", - "TND", - "TOP", - "TRY", - "TTD", - "TVD", - "TWD", - "TZS", - "UAH", - "UGX", - "USD", - "UYU", - "UZS", - "VEF", - "VND", - "VUV", - "WST", - "XAF", - "XCD", - "XOF", - "XPF", - "YER", - "ZAR", - "ZMW", - "LOGICAL", - "CUSTOM", - ] - """Currency code (ISO 4217 or crypto)""" - - description: str - """Description of the line item""" - - price: DataDiffAddDiffEntryItemPrice - """Price breakdown containing amount, unit price, and quantity""" - - product_id: str - """ID of the product/catalog item""" - - tags: List[DataDiffAddDiffEntryItemTag] - """Metadata tags for this line item""" - - type: Literal["payin", "payout"] - """The type of the line item""" - - user_id: str - """External ID of the user associated with this line item""" - - -class DataDiffAddDiffEntry(BaseModel): - item: DataDiffAddDiffEntryItem - """Invoice line item object""" - - op: Literal["add"] - """A line item was added""" - - -class DataDiffUpdateDiffEntryNewPrice(BaseModel): - """Price breakdown containing amount, unit price, and quantity""" - - amount: str - """Total amount in smallest currency unit (represented as string for bigint)""" - - quantity: int - """Quantity of units for this line item""" - - unit_price: str - """Unit price in smallest currency unit (represented as string for bigint)""" - - -class DataDiffUpdateDiffEntryOldPrice(BaseModel): - """Price breakdown containing amount, unit price, and quantity""" - - amount: str - """Total amount in smallest currency unit (represented as string for bigint)""" - - quantity: int - """Quantity of units for this line item""" - - unit_price: str - """Unit price in smallest currency unit (represented as string for bigint)""" - - -class DataDiffUpdateDiffEntry(BaseModel): - id: str - """ID of the updated line item""" - - new_amount: str - """Deprecated: use new_price.amount instead. New amount after the update""" - - new_price: DataDiffUpdateDiffEntryNewPrice - """Price breakdown containing amount, unit price, and quantity""" - - old_amount: str - """Deprecated: use old_price.amount instead. Amount before the update""" - - old_price: DataDiffUpdateDiffEntryOldPrice - """Price breakdown containing amount, unit price, and quantity""" - - op: Literal["update"] - """A line item was updated""" - - -class DataDiffDeleteDiffEntryItemPrice(BaseModel): - """Price breakdown containing amount, unit price, and quantity""" - - amount: str - """Total amount in smallest currency unit (represented as string for bigint)""" - - quantity: int - """Quantity of units for this line item""" - - unit_price: str - """Unit price in smallest currency unit (represented as string for bigint)""" - - -class DataDiffDeleteDiffEntryItemTag(BaseModel): - """A key-value tag pair""" - - key: str - """Tag key""" - - value: str - """Tag value""" - - -class DataDiffDeleteDiffEntryItem(BaseModel): - """Invoice line item object""" - - id: str - """Unique identifier for the line item""" - - amount: str - """Deprecated: use price.amount instead. - - Total amount in smallest currency unit (represented as string for bigint) - """ - - currency_code: Literal[ - "ADA", - "BTC", - "DAI", - "ETH", - "SOL", - "USDC", - "USDT", - "USDG", - "EURC", - "CADC", - "CADT", - "XLM", - "UNI", - "BCH", - "LTC", - "AAVE", - "LINK", - "MATIC", - "PTS", - "AED", - "AFN", - "ALL", - "AMD", - "ANG", - "AOA", - "ARS", - "AUD", - "AWG", - "AZN", - "BAM", - "BBD", - "BDT", - "BGN", - "BHD", - "BIF", - "BMD", - "BND", - "BOB", - "BRL", - "BSD", - "BTN", - "BWP", - "BYR", - "BZD", - "CAD", - "CDF", - "CHF", - "CLP", - "CNY", - "COP", - "CRC", - "CUC", - "CUP", - "CVE", - "CZK", - "DJF", - "DKK", - "DOP", - "DZD", - "EGP", - "ERN", - "ETB", - "EUR", - "FJD", - "FKP", - "GBP", - "GEL", - "GGP", - "GHS", - "GIP", - "GMD", - "GNF", - "GTQ", - "GYD", - "HKD", - "HNL", - "HRK", - "HTG", - "HUF", - "IDR", - "ILS", - "IMP", - "INR", - "IQD", - "IRR", - "ISK", - "JMD", - "JOD", - "JPY", - "KES", - "KGS", - "KHR", - "KMF", - "KPW", - "KRW", - "KWD", - "KYD", - "KZT", - "LAK", - "LBP", - "LKR", - "LRD", - "LSL", - "LYD", - "MAD", - "MDL", - "MGA", - "MKD", - "MMK", - "MNT", - "MOP", - "MUR", - "MVR", - "MWK", - "MXN", - "MYR", - "MZN", - "NAD", - "NGN", - "NIO", - "NOK", - "NPR", - "NZD", - "OMR", - "PAB", - "PEN", - "PGK", - "PHP", - "PKR", - "PLN", - "PYG", - "QAR", - "RON", - "RSD", - "RUB", - "RWF", - "SAR", - "SBD", - "SCR", - "SDG", - "SEK", - "SGD", - "SHP", - "SLL", - "SOS", - "SPL", - "SRD", - "SVC", - "SYP", - "STN", - "SZL", - "THB", - "TJS", - "TMT", - "TND", - "TOP", - "TRY", - "TTD", - "TVD", - "TWD", - "TZS", - "UAH", - "UGX", - "USD", - "UYU", - "UZS", - "VEF", - "VND", - "VUV", - "WST", - "XAF", - "XCD", - "XOF", - "XPF", - "YER", - "ZAR", - "ZMW", - "LOGICAL", - "CUSTOM", - ] - """Currency code (ISO 4217 or crypto)""" - - description: str - """Description of the line item""" - - price: DataDiffDeleteDiffEntryItemPrice - """Price breakdown containing amount, unit price, and quantity""" - - product_id: str - """ID of the product/catalog item""" - - tags: List[DataDiffDeleteDiffEntryItemTag] - """Metadata tags for this line item""" - - type: Literal["payin", "payout"] - """The type of the line item""" - - user_id: str - """External ID of the user associated with this line item""" - - -class DataDiffDeleteDiffEntry(BaseModel): - item: DataDiffDeleteDiffEntryItem - """Invoice line item object""" - - op: Literal["delete"] - """A line item was deleted""" - - -DataDiff: TypeAlias = Union[DataDiffAddDiffEntry, DataDiffUpdateDiffEntry, DataDiffDeleteDiffEntry] - - -class Data(Invoice): - """A versioned snapshot of an invoice""" - - diff: Optional[List[DataDiff]] = None - """Cumulative diff of changes applied to the invoice""" - - version: Optional[float] = None # type: ignore - """Version number of this invoice snapshot""" +__all__ = ["InvoiceListHistoryResponse"] class InvoiceListHistoryResponse(BaseModel): - """Version history of an invoice""" - - data: List[Data] + data: List[Invoice] + """Version history of the invoice.""" diff --git a/src/fragment/types/invoice_list_response.py b/src/fragment/types/invoice_list_response.py index 8f42ec0..b9a2949 100644 --- a/src/fragment/types/invoice_list_response.py +++ b/src/fragment/types/invoice_list_response.py @@ -9,6 +9,5 @@ class InvoiceListResponse(BaseModel): - """List of invoices""" - data: List[Invoice] + """List of invoices.""" diff --git a/src/fragment/types/invoice_retrieve_response.py b/src/fragment/types/invoice_retrieve_response.py index a0d6748..77389ce 100644 --- a/src/fragment/types/invoice_retrieve_response.py +++ b/src/fragment/types/invoice_retrieve_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import List from datetime import datetime from typing_extensions import Literal @@ -27,87 +27,117 @@ class DataBalanceNet(BaseModel): + """Net balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataBalancePayins(BaseModel): + """Payins balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataBalancePayouts(BaseModel): + """Payouts balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataBalance(BaseModel): currency: str - """Currency code""" + """ISO 4217 or crypto currency code.""" net: DataBalanceNet + """Net balance breakdown.""" payins: DataBalancePayins + """Payins balance breakdown.""" payouts: DataBalancePayouts + """Payouts balance breakdown.""" class DataPaymentTransactionTag(BaseModel): - """A key-value tag pair""" + """A key-value tag pair.""" key: str - """Tag key""" + """Tag key.""" value: str - """Tag value""" + """Tag value.""" class DataPaymentTransaction(BaseModel): - """Reference to a transaction by encoded ID and external ID.""" + """Transaction the payment is applied to.""" id: str - """Encoded transaction ID.""" + """FRAGMENT generated unique ID.""" external_id: str - """External transaction ID.""" + """User-provided unique ID.""" tags: List[DataPaymentTransactionTag] - """Metadata tags from the parent transaction.""" + """Tags from the parent transaction.""" class DataPaymentUser(BaseModel): - """User reference in API responses: Fragment user id and optional external_id.""" + """User associated with the payment.""" id: str - """FRAGMENT generated ID of the user""" + """FRAGMENT generated unique ID.""" - external_id: Optional[str] = None - """External ID of the user""" + external_id: str + """User-provided unique ID.""" class DataPayment(BaseModel): - """A payment allocated to this invoice.""" + """A payment allocated to the invoice.""" amount: str - """Amount allocated in smallest currency unit as stringified bigint.""" + """ + Amount allocated as a string in the smallest currency unit, such as cents for + USD. + """ currency: Literal[ "ADA", @@ -290,86 +320,116 @@ class DataPayment(BaseModel): "LOGICAL", "CUSTOM", ] - """Currency code (ISO 4217 or crypto)""" + """ISO 4217 or crypto currency code.""" posted: datetime - """Posted timestamp of the parent transaction in ISO 8601 format.""" + """Timestamp when the parent transaction was posted. Uses ISO 8601 format.""" transaction: DataPaymentTransaction - """Reference to a transaction by encoded ID and external ID.""" + """Transaction the payment is applied to.""" type: Literal["payin", "payout"] - """The type of the payment.""" + """Type of the payment.""" user: DataPaymentUser - """User reference in API responses: Fragment user id and optional external_id.""" + """User associated with the payment.""" class DataUserBalanceNet(BaseModel): + """Net balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataUserBalancePayins(BaseModel): + """Payins balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataUserBalancePayouts(BaseModel): + """Payouts balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataUserBalance(BaseModel): currency: str - """Currency code""" + """ISO 4217 or crypto currency code.""" net: DataUserBalanceNet + """Net balance breakdown.""" payins: DataUserBalancePayins + """Payins balance breakdown.""" payouts: DataUserBalancePayouts + """Payouts balance breakdown.""" class DataUser(BaseModel): id: str - """User/party ID""" + """User-provided unique external ID.""" balances: List[DataUserBalance] - """Per-currency balance breakdown for this user""" + """Per-currency balance breakdown for the user.""" + + external_id: str + """User-provided unique ID.""" class Data(Invoice): - """Invoice with balance details""" + """Invoice with balance details.""" balances: List[DataBalance] - """Invoice-level balances by currency: payins, payouts, and net (payins - payouts)""" + """Invoice-level balances by currency.""" payments: List[DataPayment] - """Transaction allocations (payments) associated with this invoice.""" + """Payments allocated to the invoice.""" users: List[DataUser] - """Users/parties involved in the invoice""" + """Users involved in the invoice.""" class InvoiceRetrieveResponse(BaseModel): data: Data - """Invoice with balance details""" + """Invoice with balance details.""" diff --git a/src/fragment/types/invoice_search_params.py b/src/fragment/types/invoice_search_params.py index c10ea93..f63f61e 100644 --- a/src/fragment/types/invoice_search_params.py +++ b/src/fragment/types/invoice_search_params.py @@ -3,17 +3,17 @@ from __future__ import annotations from typing import Iterable -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict __all__ = ["InvoiceSearchParams", "Filter", "FilterTags", "FilterTagsAll", "FilterTagsAny", "PageInfo"] class InvoiceSearchParams(TypedDict, total=False): filter: Required[Filter] - """Filter criteria for the search""" + """Filter criteria for the search.""" - page_info: Required[PageInfo] - """Pagination parameters""" + page_info: PageInfo + """Pagination parameters.""" class FilterTagsAll(TypedDict, total=False): @@ -53,14 +53,20 @@ class FilterTags(TypedDict, total=False): """ all: Iterable[FilterTagsAll] - """Returns invoices matching every specified tag (AND).""" + """Returns invoices matching every specified tag, using AND logic.""" any: Iterable[FilterTagsAny] - """Returns invoices matching at least one of the specified tags (OR).""" + """Returns invoices matching at least one of the specified tags, using OR logic.""" class Filter(TypedDict, total=False): - """Filter criteria for the search""" + """Filter criteria for the search.""" + + status: Literal["open"] + """Filter by invoice status. + + `open` returns invoices with non-zero clearing account balances. + """ tags: FilterTags """Tag-based filter criteria. @@ -71,10 +77,10 @@ class Filter(TypedDict, total=False): class PageInfo(TypedDict, total=False): - """Pagination parameters""" + """Pagination parameters.""" after: str - """Cursor for fetching the next page of results""" + """Cursor for fetching the next page of results.""" limit: int """Number of results to return. Defaults to 20.""" diff --git a/src/fragment/types/invoice_search_response.py b/src/fragment/types/invoice_search_response.py index 57102c0..fa1ed31 100644 --- a/src/fragment/types/invoice_search_response.py +++ b/src/fragment/types/invoice_search_response.py @@ -29,87 +29,117 @@ class DataInvoiceBalanceNet(BaseModel): + """Net balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataInvoiceBalancePayins(BaseModel): + """Payins balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataInvoiceBalancePayouts(BaseModel): + """Payouts balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataInvoiceBalance(BaseModel): currency: str - """Currency code""" + """ISO 4217 or crypto currency code.""" net: DataInvoiceBalanceNet + """Net balance breakdown.""" payins: DataInvoiceBalancePayins + """Payins balance breakdown.""" payouts: DataInvoiceBalancePayouts + """Payouts balance breakdown.""" class DataInvoicePaymentTransactionTag(BaseModel): - """A key-value tag pair""" + """A key-value tag pair.""" key: str - """Tag key""" + """Tag key.""" value: str - """Tag value""" + """Tag value.""" class DataInvoicePaymentTransaction(BaseModel): - """Reference to a transaction by encoded ID and external ID.""" + """Transaction the payment is applied to.""" id: str - """Encoded transaction ID.""" + """FRAGMENT generated unique ID.""" external_id: str - """External transaction ID.""" + """User-provided unique ID.""" tags: List[DataInvoicePaymentTransactionTag] - """Metadata tags from the parent transaction.""" + """Tags from the parent transaction.""" class DataInvoicePaymentUser(BaseModel): - """User reference in API responses: Fragment user id and optional external_id.""" + """User associated with the payment.""" id: str - """FRAGMENT generated ID of the user""" + """FRAGMENT generated unique ID.""" - external_id: Optional[str] = None - """External ID of the user""" + external_id: str + """User-provided unique ID.""" class DataInvoicePayment(BaseModel): - """A payment allocated to this invoice.""" + """A payment allocated to the invoice.""" amount: str - """Amount allocated in smallest currency unit as stringified bigint.""" + """ + Amount allocated as a string in the smallest currency unit, such as cents for + USD. + """ currency: Literal[ "ADA", @@ -292,102 +322,135 @@ class DataInvoicePayment(BaseModel): "LOGICAL", "CUSTOM", ] - """Currency code (ISO 4217 or crypto)""" + """ISO 4217 or crypto currency code.""" posted: datetime - """Posted timestamp of the parent transaction in ISO 8601 format.""" + """Timestamp when the parent transaction was posted. Uses ISO 8601 format.""" transaction: DataInvoicePaymentTransaction - """Reference to a transaction by encoded ID and external ID.""" + """Transaction the payment is applied to.""" type: Literal["payin", "payout"] - """The type of the payment.""" + """Type of the payment.""" user: DataInvoicePaymentUser - """User reference in API responses: Fragment user id and optional external_id.""" + """User associated with the payment.""" class DataInvoiceUserBalanceNet(BaseModel): + """Net balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataInvoiceUserBalancePayins(BaseModel): + """Payins balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataInvoiceUserBalancePayouts(BaseModel): + """Payouts balance breakdown.""" + actual: str - """Actual amount (represented as string)""" + """Actual amount as a string in the smallest currency unit, such as cents for USD.""" expected: str - """Expected amount (represented as string)""" + """ + Expected amount as a string in the smallest currency unit, such as cents for + USD. + """ remaining: str - """Remaining amount (expected - actual, represented as string)""" + """ + Remaining amount as a string in the smallest currency unit, such as cents for + USD. + """ class DataInvoiceUserBalance(BaseModel): currency: str - """Currency code""" + """ISO 4217 or crypto currency code.""" net: DataInvoiceUserBalanceNet + """Net balance breakdown.""" payins: DataInvoiceUserBalancePayins + """Payins balance breakdown.""" payouts: DataInvoiceUserBalancePayouts + """Payouts balance breakdown.""" class DataInvoiceUser(BaseModel): id: str - """User/party ID""" + """User-provided unique external ID.""" balances: List[DataInvoiceUserBalance] - """Per-currency balance breakdown for this user""" + """Per-currency balance breakdown for the user.""" + + external_id: str + """User-provided unique ID.""" class DataInvoice(Invoice): - """Invoice with balance details""" + """Invoice with balance details.""" balances: List[DataInvoiceBalance] - """Invoice-level balances by currency: payins, payouts, and net (payins - payouts)""" + """Invoice-level balances by currency.""" payments: List[DataInvoicePayment] - """Transaction allocations (payments) associated with this invoice.""" + """Payments allocated to the invoice.""" users: List[DataInvoiceUser] - """Users/parties involved in the invoice""" + """Users involved in the invoice.""" class DataPageInfo(BaseModel): """Pagination cursors.""" next_cursor: Optional[str] = None - """Cursor to fetch the next page of results""" + """Cursor to fetch the next page of results.""" class Data(BaseModel): + """Search results for invoices.""" + invoices: List[DataInvoice] - """List of invoices matching the search criteria""" + """Invoices matching the search criteria.""" page_info: DataPageInfo """Pagination cursors.""" class InvoiceSearchResponse(BaseModel): - """Response body for searching invoices""" + """Search results for invoices.""" data: Data + """Search results for invoices.""" diff --git a/src/fragment/types/invoice_update_params.py b/src/fragment/types/invoice_update_params.py index ad3ca78..c29afab 100644 --- a/src/fragment/types/invoice_update_params.py +++ b/src/fragment/types/invoice_update_params.py @@ -20,91 +20,88 @@ "LineItemsUpdateTags", "LineItemsUpdateTagsCreate", "LineItemsUpdateTagsDelete", + "LineItemsUpdateTagsSet", "LineItemsUpdateTagsUpdate", "Tags", "TagsCreate", "TagsDelete", + "TagsSet", "TagsUpdate", ] class InvoiceUpdateParams(TypedDict, total=False): current_invoice_version: Required[float] - """The current version of the invoice. - - Must match the stored version for the update to succeed (optimistic - concurrency). - """ + """Current version of the invoice. Must match the stored version.""" line_items: LineItems + """Line item updates.""" tags: Tags + """Tag updates.""" class LineItemsCreateUserID(TypedDict, total=False): id: Required[str] - """FRAGMENT generated ID of the user""" + """FRAGMENT generated unique ID.""" class LineItemsCreateUserExternalID(TypedDict, total=False): external_id: Required[str] - """External ID of the user""" + """User-provided unique ID.""" LineItemsCreateUser: TypeAlias = Union[LineItemsCreateUserID, LineItemsCreateUserExternalID] class LineItemsCreatePrice(TypedDict, total=False): - """Price breakdown. Provide amount, or unit_price + quantity, or all three.""" + """Price breakdown. Provide amount, or unit_price and quantity, or all three.""" amount: str - """Total amount in smallest currency unit. + """Total amount as a string in the smallest currency unit, such as cents for USD. Required if unit_price and quantity are not provided. """ quantity: int - """Number of units for this line item.""" + """Number of units for the line item.""" unit_price: str - """Price per unit in smallest currency unit.""" + """ + Price per unit as a string in the smallest currency unit, such as cents for USD. + """ class LineItemsCreateTag(TypedDict, total=False): - """A key-value tag pair for metadata""" + """A key-value tag pair for metadata.""" key: Required[str] - """Tag key. - - Must be a valid safe string (no special characters like #, /, :). Max 50 - characters. - """ + """Tag key. Must not contain #, /, or :. Max 50 characters.""" value: Required[str] - """Tag value. - - Must be a valid safe string (no special characters like #, /, :). Max 200 - characters. - """ + """Tag value. Must not contain #, /, or :. Max 200 characters.""" class LineItemsCreate(TypedDict, total=False): """Data to create a line item.""" description: Required[str] - """Description of the line item""" + """Description of the line item.""" product_id: Required[str] - """ID of the product/catalog item""" + """Unique identifier for the product.""" type: Required[Literal["payin", "payout"]] - """The type of the line item""" + """Type of the line item.""" user: Required[LineItemsCreateUser] - """Identifies a user by Fragment-generated id or external_id (request body).""" + """Identifies a user by `id` or `external_id`.""" amount: str - """Deprecated: use price instead. Total amount in smallest currency unit.""" + """Total amount as a string in the smallest currency unit, such as cents for USD. + + Deprecated, use price instead. + """ currency_code: Literal[ "ADA", @@ -287,160 +284,157 @@ class LineItemsCreate(TypedDict, total=False): "LOGICAL", "CUSTOM", ] - """Currency code (ISO 4217 or crypto)""" + """ISO 4217 or crypto currency code.""" price: LineItemsCreatePrice - """Price breakdown. Provide amount, or unit_price + quantity, or all three.""" + """Price breakdown. Provide amount, or unit_price and quantity, or all three.""" tags: Iterable[LineItemsCreateTag] - """Optional metadata tags for this line item""" + """Tags for the line item.""" class LineItemsDelete(TypedDict, total=False): id: Required[str] - """ID of the line item to delete""" + """Unique identifier for the line item to delete.""" class LineItemsUpdatePrice(TypedDict, total=False): quantity: Required[int] - """Number of units for this line item.""" + """Number of units for the line item.""" unit_price: Required[str] - """Price per unit in smallest currency unit.""" + """ + Price per unit as a string in the smallest currency unit, such as cents for USD. + """ amount: str - """Total amount in smallest currency unit.""" + """Total amount as a string in the smallest currency unit, such as cents for USD.""" class LineItemsUpdateTagsCreate(TypedDict, total=False): - """A key-value tag pair for metadata""" + """A key-value tag pair for metadata.""" key: Required[str] - """Tag key. - - Must be a valid safe string (no special characters like #, /, :). Max 50 - characters. - """ + """Tag key. Must not contain #, /, or :. Max 50 characters.""" value: Required[str] - """Tag value. - - Must be a valid safe string (no special characters like #, /, :). Max 200 - characters. - """ + """Tag value. Must not contain #, /, or :. Max 200 characters.""" class LineItemsUpdateTagsDelete(TypedDict, total=False): key: Required[str] - """Tag key to delete""" + """Tag key to delete.""" -class LineItemsUpdateTagsUpdate(TypedDict, total=False): - """A key-value tag pair for metadata""" +class LineItemsUpdateTagsSet(TypedDict, total=False): + """A key-value tag pair for metadata.""" key: Required[str] - """Tag key. - - Must be a valid safe string (no special characters like #, /, :). Max 50 - characters. - """ + """Tag key. Must not contain #, /, or :. Max 50 characters.""" value: Required[str] - """Tag value. + """Tag value. Must not contain #, /, or :. Max 200 characters.""" - Must be a valid safe string (no special characters like #, /, :). Max 200 - characters. - """ + +class LineItemsUpdateTagsUpdate(TypedDict, total=False): + """A key-value tag pair for metadata.""" + + key: Required[str] + """Tag key. Must not contain #, /, or :. Max 50 characters.""" + + value: Required[str] + """Tag value. Must not contain #, /, or :. Max 200 characters.""" class LineItemsUpdateTags(TypedDict, total=False): + """Tag updates.""" + create: Iterable[LineItemsUpdateTagsCreate] - """Tags to add""" + """Tags to create. The tag key must not already exist.""" delete: Iterable[LineItemsUpdateTagsDelete] - """Tags to remove by key""" + """Tags to remove.""" - update: Iterable[LineItemsUpdateTagsUpdate] - """Tags to update. + set: Iterable[LineItemsUpdateTagsSet] + """Tags to set. Creates a new tag or updates an existing tag.""" - The key identifies the existing tag; the value is the new value. - """ + update: Iterable[LineItemsUpdateTagsUpdate] + """Tags to update. The tag key must already exist.""" class LineItemsUpdate(TypedDict, total=False): - """Partial update for an existing line item. All fields except id are optional.""" + """Data for updating a line item.""" id: Required[str] - """ID of the line item to update""" + """Unique identifier for the line item to update.""" description: str price: LineItemsUpdatePrice tags: LineItemsUpdateTags + """Tag updates.""" class LineItems(TypedDict, total=False): + """Line item updates.""" + create: Iterable[LineItemsCreate] - """Line items to add to the invoice""" + """Line items to add to the invoice.""" delete: Iterable[LineItemsDelete] - """Line items to remove from the invoice""" + """Line items to remove from the invoice.""" update: Iterable[LineItemsUpdate] - """Existing line items to update""" + """Existing line items to update.""" class TagsCreate(TypedDict, total=False): - """A key-value tag pair for metadata""" + """A key-value tag pair for metadata.""" key: Required[str] - """Tag key. - - Must be a valid safe string (no special characters like #, /, :). Max 50 - characters. - """ + """Tag key. Must not contain #, /, or :. Max 50 characters.""" value: Required[str] - """Tag value. - - Must be a valid safe string (no special characters like #, /, :). Max 200 - characters. - """ + """Tag value. Must not contain #, /, or :. Max 200 characters.""" class TagsDelete(TypedDict, total=False): key: Required[str] - """Tag key to delete""" + """Tag key to delete.""" -class TagsUpdate(TypedDict, total=False): - """A key-value tag pair for metadata""" +class TagsSet(TypedDict, total=False): + """A key-value tag pair for metadata.""" key: Required[str] - """Tag key. - - Must be a valid safe string (no special characters like #, /, :). Max 50 - characters. - """ + """Tag key. Must not contain #, /, or :. Max 50 characters.""" value: Required[str] - """Tag value. + """Tag value. Must not contain #, /, or :. Max 200 characters.""" - Must be a valid safe string (no special characters like #, /, :). Max 200 - characters. - """ + +class TagsUpdate(TypedDict, total=False): + """A key-value tag pair for metadata.""" + + key: Required[str] + """Tag key. Must not contain #, /, or :. Max 50 characters.""" + + value: Required[str] + """Tag value. Must not contain #, /, or :. Max 200 characters.""" class Tags(TypedDict, total=False): + """Tag updates.""" + create: Iterable[TagsCreate] - """Tags to add""" + """Tags to create. The tag key must not already exist.""" delete: Iterable[TagsDelete] - """Tags to remove by key""" + """Tags to remove.""" - update: Iterable[TagsUpdate] - """Tags to update. + set: Iterable[TagsSet] + """Tags to set. Creates a new tag or updates an existing tag.""" - The key identifies the existing tag; the value is the new value. - """ + update: Iterable[TagsUpdate] + """Tags to update. The tag key must already exist.""" diff --git a/src/fragment/types/invoice_update_response.py b/src/fragment/types/invoice_update_response.py index 4f8409a..2ceb944 100644 --- a/src/fragment/types/invoice_update_response.py +++ b/src/fragment/types/invoice_update_response.py @@ -8,4 +8,4 @@ class InvoiceUpdateResponse(BaseModel): data: Invoice - """Invoice object""" + """Invoice object.""" diff --git a/src/fragment/types/product.py b/src/fragment/types/product.py index 23f9c30..66b73b8 100644 --- a/src/fragment/types/product.py +++ b/src/fragment/types/product.py @@ -12,45 +12,45 @@ class PaidByRole(BaseModel): """Role reference in product API responses.""" id: str - """The unique ID of the role""" + """FRAGMENT generated unique ID.""" name: str - """The name of the role""" + """Name of the role.""" class PaidToRole(BaseModel): """Role reference in product API responses.""" id: str - """The unique ID of the role""" + """FRAGMENT generated unique ID.""" name: str - """The name of the role""" + """Name of the role.""" class Product(BaseModel): - """Product object""" + """Product object.""" id: str - """Unique identifier for the product""" + """FRAGMENT generated unique ID.""" code: str - """User-defined product identifier.""" + """Product code.""" created: datetime - """ISO 8601 timestamp when the product was created""" + """Timestamp when the product was created. Uses ISO 8601 format.""" paid_by_roles: List[PaidByRole] - """User roles that can pay for this product""" + """Roles that can pay for the product.""" paid_to_roles: List[PaidToRole] - """User roles that receive payment for this product""" + """Roles that can receive payment for the product.""" update_version: float - """Version number for optimistic locking""" + """Current version of the product.""" workspace_id: str - """Workspace ID this product belongs to""" + """Workspace ID of the product.""" description: Optional[str] = None - """Description of the product""" + """Product description.""" diff --git a/src/fragment/types/product_create_params.py b/src/fragment/types/product_create_params.py index 99c8cba..07e7515 100644 --- a/src/fragment/types/product_create_params.py +++ b/src/fragment/types/product_create_params.py @@ -18,34 +18,34 @@ class ProductCreateParams(TypedDict, total=False): code: Required[str] - """Product code (unique identifier)""" + """Unique product code.""" description: str - """Description of the product""" + """Product description.""" paid_by_roles: Iterable[PaidByRole] - """Roles that can pay for this product. + """Roles that can pay for the product. - Reference roles by id or name. At least one of paid_by_roles or paid_to_roles - must be provided. + Reference roles by `id` or `name`. At least one of `paid_by_roles` or + `paid_to_roles` must be provided. """ paid_to_roles: Iterable[PaidToRole] - """Roles that receive payment for this product. + """Roles that can receive payment for the product. - Reference roles by id or name. At least one of paid_by_roles or paid_to_roles - must be provided. + Reference roles by `id` or `name`. At least one of `paid_by_roles` or + `paid_to_roles` must be provided. """ class PaidByRoleID(TypedDict, total=False): id: Required[str] - """The unique ID of the role""" + """FRAGMENT generated unique ID.""" class PaidByRoleName(TypedDict, total=False): name: Required[str] - """The name of the role""" + """Name of the role.""" PaidByRole: TypeAlias = Union[PaidByRoleID, PaidByRoleName] @@ -53,12 +53,12 @@ class PaidByRoleName(TypedDict, total=False): class PaidToRoleID(TypedDict, total=False): id: Required[str] - """The unique ID of the role""" + """FRAGMENT generated unique ID.""" class PaidToRoleName(TypedDict, total=False): name: Required[str] - """The name of the role""" + """Name of the role.""" PaidToRole: TypeAlias = Union[PaidToRoleID, PaidToRoleName] diff --git a/src/fragment/types/product_create_response.py b/src/fragment/types/product_create_response.py index f921f55..389e24b 100644 --- a/src/fragment/types/product_create_response.py +++ b/src/fragment/types/product_create_response.py @@ -8,4 +8,4 @@ class ProductCreateResponse(BaseModel): data: Product - """Product object""" + """Product object.""" diff --git a/src/fragment/types/product_list_response.py b/src/fragment/types/product_list_response.py index 8b2c8b1..7c4e7c6 100644 --- a/src/fragment/types/product_list_response.py +++ b/src/fragment/types/product_list_response.py @@ -9,6 +9,5 @@ class ProductListResponse(BaseModel): - """List of products""" - data: List[Product] + """List of products.""" diff --git a/src/fragment/types/product_retrieve_response.py b/src/fragment/types/product_retrieve_response.py index ab4a8dc..594d653 100644 --- a/src/fragment/types/product_retrieve_response.py +++ b/src/fragment/types/product_retrieve_response.py @@ -8,4 +8,4 @@ class ProductRetrieveResponse(BaseModel): data: Product - """Product object""" + """Product object.""" diff --git a/src/fragment/types/role.py b/src/fragment/types/role.py index d094b48..0716049 100644 --- a/src/fragment/types/role.py +++ b/src/fragment/types/role.py @@ -6,10 +6,10 @@ class Role(BaseModel): - """Role object""" + """Role object.""" id: str - """Unique role ID""" + """FRAGMENT generated unique ID.""" role: str - """Name of the role""" + """Name of the role.""" diff --git a/src/fragment/types/role_create_params.py b/src/fragment/types/role_create_params.py index 855e332..cde32ed 100644 --- a/src/fragment/types/role_create_params.py +++ b/src/fragment/types/role_create_params.py @@ -9,4 +9,4 @@ class RoleCreateParams(TypedDict, total=False): role: Required[str] - """Name of the role""" + """Name of the role.""" diff --git a/src/fragment/types/role_create_response.py b/src/fragment/types/role_create_response.py index 9f1dedd..c3baf28 100644 --- a/src/fragment/types/role_create_response.py +++ b/src/fragment/types/role_create_response.py @@ -8,4 +8,4 @@ class RoleCreateResponse(BaseModel): data: Role - """Role object""" + """Role object.""" diff --git a/src/fragment/types/role_list_response.py b/src/fragment/types/role_list_response.py index f945539..0d8c7f9 100644 --- a/src/fragment/types/role_list_response.py +++ b/src/fragment/types/role_list_response.py @@ -9,6 +9,7 @@ class RoleListResponse(BaseModel): - """List of roles""" + """List of roles.""" data: List[Role] + """List of roles.""" diff --git a/src/fragment/types/transaction.py b/src/fragment/types/transaction.py index c6f9908..b1ce279 100644 --- a/src/fragment/types/transaction.py +++ b/src/fragment/types/transaction.py @@ -10,70 +10,74 @@ class Account(BaseModel): - """External account reference on transaction responses.""" + """External account for the transaction.""" id: str - """User-facing encoded account ID.""" + """FRAGMENT generated unique ID.""" external_id: str - """External account reference ID.""" + """User-provided unique ID.""" class AllocationUser(BaseModel): - """User reference in API responses: Fragment user id and optional external_id.""" + """User associated with the allocation.""" id: str - """FRAGMENT generated ID of the user""" + """FRAGMENT generated unique ID.""" - external_id: Optional[str] = None - """External ID of the user""" + external_id: str + """User-provided unique ID.""" class Allocation(BaseModel): - """Transaction allocation against an invoice.""" + """An allocation linking a transaction to an invoice.""" amount: str - """Amount to allocate in smallest currency unit as stringified bigint.""" + """ + Allocated amount, as a positive string in the smallest currency unit, such as + cents for USD. + """ invoice_id: str - """The invoice to allocate against.""" + """Invoice the allocation is applied against.""" type: Literal["invoice_payin", "invoice_payout"] - """The type of allocation.""" + """Type of allocation.""" user: AllocationUser - """User reference in API responses: Fragment user id and optional external_id.""" + """User associated with the allocation.""" class Tag(BaseModel): - """A key-value tag pair""" + """A key-value tag pair.""" key: str - """Tag key""" + """Tag key.""" value: str - """Tag value""" + """Tag value.""" class Transaction(BaseModel): """Transaction object.""" id: str - """User-facing encoded transaction ID.""" + """FRAGMENT generated unique ID.""" account: Account - """External account reference on transaction responses.""" + """External account for the transaction.""" allocations: List[Allocation] + """Allocations applied to the transaction.""" amount: str """ - Amount in smallest currency unit as stringified bigint (can be positive or - negative). + Transaction amount, as a string in the smallest currency unit, such as cents for + USD. Can be positive or negative. """ created: datetime - """Creation timestamp.""" + """Timestamp when the transaction was created. Uses ISO 8601 format.""" currency: Literal[ "ADA", @@ -256,22 +260,22 @@ class Transaction(BaseModel): "LOGICAL", "CUSTOM", ] - """Currency code (ISO 4217 or crypto)""" + """ISO 4217 or crypto currency code.""" external_id: str - """External idempotency key provided by the user.""" + """User-provided unique ID.""" posted: datetime - """Posted timestamp in ISO 8601 format.""" + """Timestamp when the transaction was posted. Uses ISO 8601 format.""" tags: List[Tag] - """Metadata tags associated with this transaction.""" + """Tags for the transaction.""" unallocated_amount: str - """Read-only amount not yet allocated.""" + """Amount not yet allocated, as a string.""" version: int - """Current version of the transaction, used for optimistic concurrency control.""" + """Current version of the transaction.""" modified: Optional[datetime] = None - """Last modified timestamp.""" + """Timestamp when the transaction was last modified. Uses ISO 8601 format.""" diff --git a/src/fragment/types/transaction_create_allocations_params.py b/src/fragment/types/transaction_create_allocations_params.py deleted file mode 100644 index 1885ef8..0000000 --- a/src/fragment/types/transaction_create_allocations_params.py +++ /dev/null @@ -1,67 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Union, Iterable -from typing_extensions import Literal, Required, TypeAlias, TypedDict - -__all__ = [ - "TransactionCreateAllocationsParams", - "AllocationUpdate", - "AllocationUpdateAddAllocationOperation", - "AllocationUpdateAddAllocationOperationUser", - "AllocationUpdateAddAllocationOperationUserID", - "AllocationUpdateAddAllocationOperationUserExternalID", - "AllocationUpdateDeleteAllocationOperation", -] - - -class TransactionCreateAllocationsParams(TypedDict, total=False): - allocation_updates: Required[Iterable[AllocationUpdate]] - """Allocation operations to apply""" - - version: Required[int] - """Current transaction version for optimistic concurrency control""" - - -class AllocationUpdateAddAllocationOperationUserID(TypedDict, total=False): - id: Required[str] - """FRAGMENT generated ID of the user""" - - -class AllocationUpdateAddAllocationOperationUserExternalID(TypedDict, total=False): - external_id: Required[str] - """External ID of the user""" - - -AllocationUpdateAddAllocationOperationUser: TypeAlias = Union[ - AllocationUpdateAddAllocationOperationUserID, AllocationUpdateAddAllocationOperationUserExternalID -] - - -class AllocationUpdateAddAllocationOperation(TypedDict, total=False): - amount: Required[str] - """Amount to allocate in smallest currency unit as stringified bigint.""" - - invoice_id: Required[str] - """The invoice to allocate against.""" - - op: Required[Literal["add"]] - """Add a new allocation""" - - type: Required[Literal["invoice_payin", "invoice_payout"]] - """The type of allocation.""" - - user: Required[AllocationUpdateAddAllocationOperationUser] - """Identifies a user by Fragment-generated id or external_id (request body).""" - - -class AllocationUpdateDeleteAllocationOperation(TypedDict, total=False): - id: Required[str] - """The ID of the allocation to remove.""" - - op: Required[Literal["delete"]] - """Delete an allocation""" - - -AllocationUpdate: TypeAlias = Union[AllocationUpdateAddAllocationOperation, AllocationUpdateDeleteAllocationOperation] diff --git a/src/fragment/types/transaction_create_params.py b/src/fragment/types/transaction_create_params.py index 8af2d0c..847df59 100644 --- a/src/fragment/types/transaction_create_params.py +++ b/src/fragment/types/transaction_create_params.py @@ -21,15 +21,18 @@ class TransactionCreateParams(TypedDict, total=False): account: Required[Account] - """Account reference. Provide id, external_id, or both.""" + """External account for the transaction. + + Identify it by `id`, `external_id`, or both. + """ allocations: Required[Iterable[Allocation]] - """Allocation entries for this transaction. Empty indicates unreconciled funds.""" + """Allocations for the transaction. An empty array indicates unreconciled funds.""" amount: Required[str] """ - Amount in smallest currency unit as stringified bigint (can be positive or - negative). + Transaction amount, as a string in the smallest currency unit, such as cents for + USD. Can be positive or negative. """ currency: Required[ @@ -215,70 +218,68 @@ class TransactionCreateParams(TypedDict, total=False): "CUSTOM", ] ] - """Currency code (ISO 4217 or crypto)""" + """ISO 4217 or crypto currency code.""" external_id: Required[str] - """External transaction ID used for idempotent sync.""" + """User-provided unique ID.""" posted: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] - """Posted timestamp in ISO 8601 format.""" + """Timestamp when the transaction was posted. Uses ISO 8601 format.""" tags: Iterable[Tag] - """Optional metadata tags for this transaction""" + """Tags for the transaction.""" class Account(TypedDict, total=False): - """Account reference. Provide id, external_id, or both.""" + """External account for the transaction. + + Identify it by `id`, `external_id`, or both. + """ id: str - """User-facing encoded account ID.""" + """FRAGMENT generated unique ID.""" external_id: str - """External account reference ID.""" + """User-provided unique ID.""" class AllocationUserID(TypedDict, total=False): id: Required[str] - """FRAGMENT generated ID of the user""" + """FRAGMENT generated unique ID.""" class AllocationUserExternalID(TypedDict, total=False): external_id: Required[str] - """External ID of the user""" + """User-provided unique ID.""" AllocationUser: TypeAlias = Union[AllocationUserID, AllocationUserExternalID] class Allocation(TypedDict, total=False): - """Transaction allocation against an invoice.""" + """An allocation linking a transaction to an invoice.""" amount: Required[str] - """Amount to allocate in smallest currency unit as stringified bigint.""" + """ + Allocation amount, as a positive string in the smallest currency unit, such as + cents for USD. + """ invoice_id: Required[str] - """The invoice to allocate against.""" + """Invoice to allocate against.""" type: Required[Literal["invoice_payin", "invoice_payout"]] - """The type of allocation.""" + """Type of allocation.""" user: Required[AllocationUser] - """Identifies a user by Fragment-generated id or external_id (request body).""" + """Identifies a user by `id` or `external_id`.""" class Tag(TypedDict, total=False): - """A key-value tag pair for metadata""" + """A key-value tag pair for metadata.""" key: Required[str] - """Tag key. - - Must be a valid safe string (no special characters like #, /, :). Max 50 - characters. - """ + """Tag key. Must not contain #, /, or :. Max 50 characters.""" value: Required[str] - """Tag value. - - Must be a valid safe string (no special characters like #, /, :). Max 200 - characters. - """ + """Tag value. Must not contain #, /, or :. Max 200 characters.""" diff --git a/src/fragment/types/transaction_list_history_response.py b/src/fragment/types/transaction_list_history_response.py index fb1338d..0f63fec 100644 --- a/src/fragment/types/transaction_list_history_response.py +++ b/src/fragment/types/transaction_list_history_response.py @@ -1,110 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing import List from .._models import BaseModel from .transaction import Transaction -__all__ = [ - "TransactionListHistoryResponse", - "Data", - "DataDiff", - "DataDiffAddAllocationDiffEntry", - "DataDiffAddAllocationDiffEntryItem", - "DataDiffAddAllocationDiffEntryItemUser", - "DataDiffDeleteAllocationDiffEntry", - "DataDiffDeleteAllocationDiffEntryItem", - "DataDiffDeleteAllocationDiffEntryItemUser", -] - - -class DataDiffAddAllocationDiffEntryItemUser(BaseModel): - """User reference in API responses: Fragment user id and optional external_id.""" - - id: str - """FRAGMENT generated ID of the user""" - - external_id: Optional[str] = None - """External ID of the user""" - - -class DataDiffAddAllocationDiffEntryItem(BaseModel): - """Transaction allocation against an invoice.""" - - amount: str - """Amount to allocate in smallest currency unit as stringified bigint.""" - - invoice_id: str - """The invoice to allocate against.""" - - type: Literal["invoice_payin", "invoice_payout"] - """The type of allocation.""" - - user: DataDiffAddAllocationDiffEntryItemUser - """User reference in API responses: Fragment user id and optional external_id.""" - - -class DataDiffAddAllocationDiffEntry(BaseModel): - item: DataDiffAddAllocationDiffEntryItem - """Transaction allocation against an invoice.""" - - op: Literal["add"] - """An allocation was added""" - - -class DataDiffDeleteAllocationDiffEntryItemUser(BaseModel): - """User reference in API responses: Fragment user id and optional external_id.""" - - id: str - """FRAGMENT generated ID of the user""" - - external_id: Optional[str] = None - """External ID of the user""" - - -class DataDiffDeleteAllocationDiffEntryItem(BaseModel): - """Transaction allocation against an invoice.""" - - amount: str - """Amount to allocate in smallest currency unit as stringified bigint.""" - - invoice_id: str - """The invoice to allocate against.""" - - type: Literal["invoice_payin", "invoice_payout"] - """The type of allocation.""" - - user: DataDiffDeleteAllocationDiffEntryItemUser - """User reference in API responses: Fragment user id and optional external_id.""" - - -class DataDiffDeleteAllocationDiffEntry(BaseModel): - item: DataDiffDeleteAllocationDiffEntryItem - """Transaction allocation against an invoice.""" - - op: Literal["delete"] - """An allocation was deleted""" - - -DataDiff: TypeAlias = Union[DataDiffAddAllocationDiffEntry, DataDiffDeleteAllocationDiffEntry] - - -class Data(Transaction): - """A versioned snapshot of a transaction""" - - diff: Optional[List[DataDiff]] = None - """Allocation changes applied in this version. - - Absent on version 1 (initial creation). Each entry describes an allocation that - was added or deleted. - """ - - version: Optional[int] = None # type: ignore - """Version number of this transaction snapshot.""" +__all__ = ["TransactionListHistoryResponse"] class TransactionListHistoryResponse(BaseModel): - """Version history of a transaction""" - - data: List[Data] + data: List[Transaction] + """List of transaction versions over time, ordered by version, oldest first.""" diff --git a/src/fragment/types/transaction_list_params.py b/src/fragment/types/transaction_list_params.py index b5b8db4..e4b4620 100644 --- a/src/fragment/types/transaction_list_params.py +++ b/src/fragment/types/transaction_list_params.py @@ -9,15 +9,15 @@ class TransactionListParams(TypedDict, total=False): account: str - """Filter by account. + """Filter by account `id` or `external_id`. - Encoded account ID (ext_account_xxx) or external_id. If the account does not - exist, returns an empty list. + If the account does not exist, returns an empty list. """ reconciliation_status: Literal["reconciled", "unreconciled"] - """Filter by reconciliation state. + """Filter by reconciliation status. - reconciled = unallocated_amount === 0; unreconciled = unallocated_amount !== 0. - Omit for all transactions. + `reconciled` returns transactions where unallocated_amount is 0. `unreconciled` + returns transactions where unallocated_amount is not 0. Omit for all + transactions. """ diff --git a/src/fragment/types/transaction_list_response.py b/src/fragment/types/transaction_list_response.py index fc72d31..3e1be12 100644 --- a/src/fragment/types/transaction_list_response.py +++ b/src/fragment/types/transaction_list_response.py @@ -9,6 +9,5 @@ class TransactionListResponse(BaseModel): - """List of transactions""" - data: List[Transaction] + """List of transaction objects matching the filter criteria.""" diff --git a/src/fragment/types/transaction_search_allocations_params.py b/src/fragment/types/transaction_search_allocations_params.py index c1c8ee8..ab556ca 100644 --- a/src/fragment/types/transaction_search_allocations_params.py +++ b/src/fragment/types/transaction_search_allocations_params.py @@ -11,15 +11,18 @@ class TransactionSearchAllocationsParams(TypedDict, total=False): filter: Required[Filter] - """Filter criteria for searching transaction allocations.""" + """Filter for searching transaction allocations.""" class FilterInvoiceID(TypedDict, total=False): + """Invoice ID filter.""" + any: Required[SequenceNotStr[str]] - """Match allocations where invoice_id is any of these values (OR).""" + """Match allocations where invoice_id is any of these values, using OR logic.""" class Filter(TypedDict, total=False): - """Filter criteria for searching transaction allocations.""" + """Filter for searching transaction allocations.""" invoice_id: Required[FilterInvoiceID] + """Invoice ID filter.""" diff --git a/src/fragment/types/transaction_search_allocations_response.py b/src/fragment/types/transaction_search_allocations_response.py index 12f6f25..81c7994 100644 --- a/src/fragment/types/transaction_search_allocations_response.py +++ b/src/fragment/types/transaction_search_allocations_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import List from datetime import datetime from typing_extensions import Literal @@ -10,51 +10,53 @@ class DataTransaction(BaseModel): - """Reference to a transaction by encoded ID and external ID.""" + """Transaction the allocation is applied to.""" id: str - """Encoded transaction ID.""" + """FRAGMENT generated unique ID.""" external_id: str - """External transaction ID.""" + """User-provided unique ID.""" class DataUser(BaseModel): - """User reference in API responses: Fragment user id and optional external_id.""" + """User associated with the allocation.""" id: str - """FRAGMENT generated ID of the user""" + """FRAGMENT generated unique ID.""" - external_id: Optional[str] = None - """External ID of the user""" + external_id: str + """User-provided unique ID.""" class Data(BaseModel): - """A flattened allocation with a reference to its parent transaction.""" + """An allocation with a reference to its parent transaction.""" id: str - """Allocation ID.""" + """FRAGMENT generated unique ID.""" amount: str - """Amount to allocate in smallest currency unit as stringified bigint.""" + """ + Allocated amount, as a positive string in the smallest currency unit, such as + cents for USD. + """ invoice_id: str - """The invoice to allocate against.""" + """Invoice the allocation is applied against.""" posted: datetime - """Posted timestamp of the parent transaction in ISO 8601 format.""" + """Timestamp when the parent transaction was posted. Uses ISO 8601 format.""" transaction: DataTransaction - """Reference to a transaction by encoded ID and external ID.""" + """Transaction the allocation is applied to.""" type: Literal["invoice_payin", "invoice_payout"] - """The type of allocation.""" + """Type of allocation.""" user: DataUser - """User reference in API responses: Fragment user id and optional external_id.""" + """User associated with the allocation.""" class TransactionSearchAllocationsResponse(BaseModel): - """Search results for transaction allocations.""" - data: List[Data] + """List of allocation search results.""" diff --git a/src/fragment/types/transaction_search_params.py b/src/fragment/types/transaction_search_params.py index bb5005b..94db272 100644 --- a/src/fragment/types/transaction_search_params.py +++ b/src/fragment/types/transaction_search_params.py @@ -5,30 +5,111 @@ from typing import Iterable from typing_extensions import Required, TypedDict -__all__ = ["TransactionSearchParams", "Filter", "FilterAccount", "FilterAccountAny"] +__all__ = [ + "TransactionSearchParams", + "Filter", + "FilterAccount", + "FilterAccountAny", + "FilterTags", + "FilterTagsAll", + "FilterTagsAny", + "PageInfo", +] class TransactionSearchParams(TypedDict, total=False): filter: Required[Filter] - """Filter criteria for searching transactions.""" + """Filter for searching transactions.""" + + page_info: PageInfo + """Pagination parameters.""" class FilterAccountAny(TypedDict, total=False): - """Account reference. Provide id, external_id, or both.""" + """External account for the transaction. + + Identify it by `id`, `external_id`, or both. + """ id: str - """User-facing encoded account ID.""" + """FRAGMENT generated unique ID.""" external_id: str - """External account reference ID.""" + """User-provided unique ID.""" class FilterAccount(TypedDict, total=False): + """Account filter.""" + any: Required[Iterable[FilterAccountAny]] - """Match transactions belonging to any of these accounts (OR).""" + """Match transactions belonging to any of these accounts, using OR logic.""" + + +class FilterTagsAll(TypedDict, total=False): + """A tag filter.""" + + key: Required[str] + """Tag key to filter on. Must be an exact match; wildcards are not supported.""" + + value: Required[str] + """Tag value pattern to filter on. + + Supports wildcards: `*` matches any characters, `?` matches a single character. + Use `\\**` or `\\??` to match literal asterisks or question marks. Use `*` to match + any value for the given key. + """ + + +class FilterTagsAny(TypedDict, total=False): + """A tag filter.""" + + key: Required[str] + """Tag key to filter on. Must be an exact match; wildcards are not supported.""" + + value: Required[str] + """Tag value pattern to filter on. + + Supports wildcards: `*` matches any characters, `?` matches a single character. + Use `\\**` or `\\??` to match literal asterisks or question marks. Use `*` to match + any value for the given key. + """ + + +class FilterTags(TypedDict, total=False): + """Tag-based filter criteria. + + When both `any` and `all` are provided, results must match every entry in `all` AND at least one entry in `any`. + """ + + all: Iterable[FilterTagsAll] + """Returns transactions matching every specified tag, using AND logic.""" + + any: Iterable[FilterTagsAny] + """ + Returns transactions matching at least one of the specified tags, using OR + logic. + """ class Filter(TypedDict, total=False): - """Filter criteria for searching transactions.""" + """Filter for searching transactions.""" + + account: FilterAccount + """Account filter.""" + + tags: FilterTags + """Tag-based filter criteria. + + When both `any` and `all` are provided, results must match every entry in `all` + AND at least one entry in `any`. + """ + + +class PageInfo(TypedDict, total=False): + """Pagination parameters.""" + + after: str + """Cursor for fetching the next page of results.""" - account: Required[FilterAccount] + limit: int + """Number of results to return. Defaults to 20.""" diff --git a/src/fragment/types/transaction_search_response.py b/src/fragment/types/transaction_search_response.py index 4f1daf9..70246fb 100644 --- a/src/fragment/types/transaction_search_response.py +++ b/src/fragment/types/transaction_search_response.py @@ -1,110 +1,34 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing import List, Optional from .._models import BaseModel from .transaction import Transaction -__all__ = [ - "TransactionSearchResponse", - "Data", - "DataDiff", - "DataDiffAddAllocationDiffEntry", - "DataDiffAddAllocationDiffEntryItem", - "DataDiffAddAllocationDiffEntryItemUser", - "DataDiffDeleteAllocationDiffEntry", - "DataDiffDeleteAllocationDiffEntryItem", - "DataDiffDeleteAllocationDiffEntryItemUser", -] +__all__ = ["TransactionSearchResponse", "DataV2", "DataV2PageInfo"] -class DataDiffAddAllocationDiffEntryItemUser(BaseModel): - """User reference in API responses: Fragment user id and optional external_id.""" +class DataV2PageInfo(BaseModel): + """Pagination cursors.""" - id: str - """FRAGMENT generated ID of the user""" + next_cursor: Optional[str] = None + """Cursor to fetch the next page of results.""" - external_id: Optional[str] = None - """External ID of the user""" +class DataV2(BaseModel): + page_info: DataV2PageInfo + """Pagination cursors.""" -class DataDiffAddAllocationDiffEntryItem(BaseModel): - """Transaction allocation against an invoice.""" + transactions: List[Transaction] + """Transactions matching the search criteria.""" - amount: str - """Amount to allocate in smallest currency unit as stringified bigint.""" - invoice_id: str - """The invoice to allocate against.""" - - type: Literal["invoice_payin", "invoice_payout"] - """The type of allocation.""" - - user: DataDiffAddAllocationDiffEntryItemUser - """User reference in API responses: Fragment user id and optional external_id.""" - - -class DataDiffAddAllocationDiffEntry(BaseModel): - item: DataDiffAddAllocationDiffEntryItem - """Transaction allocation against an invoice.""" - - op: Literal["add"] - """An allocation was added""" - - -class DataDiffDeleteAllocationDiffEntryItemUser(BaseModel): - """User reference in API responses: Fragment user id and optional external_id.""" - - id: str - """FRAGMENT generated ID of the user""" - - external_id: Optional[str] = None - """External ID of the user""" - - -class DataDiffDeleteAllocationDiffEntryItem(BaseModel): - """Transaction allocation against an invoice.""" - - amount: str - """Amount to allocate in smallest currency unit as stringified bigint.""" - - invoice_id: str - """The invoice to allocate against.""" - - type: Literal["invoice_payin", "invoice_payout"] - """The type of allocation.""" - - user: DataDiffDeleteAllocationDiffEntryItemUser - """User reference in API responses: Fragment user id and optional external_id.""" - - -class DataDiffDeleteAllocationDiffEntry(BaseModel): - item: DataDiffDeleteAllocationDiffEntryItem - """Transaction allocation against an invoice.""" - - op: Literal["delete"] - """An allocation was deleted""" - - -DataDiff: TypeAlias = Union[DataDiffAddAllocationDiffEntry, DataDiffDeleteAllocationDiffEntry] - - -class Data(Transaction): - """A versioned snapshot of a transaction""" - - diff: Optional[List[DataDiff]] = None - """Allocation changes applied in this version. +class TransactionSearchResponse(BaseModel): + data: List[Transaction] + """Deprecated. - Absent on version 1 (initial creation). Each entry describes an allocation that - was added or deleted. + Use `data_v2.transactions` instead. Returns the full unpaginated list of + matching transactions. """ - version: Optional[int] = None # type: ignore - """Version number of this transaction snapshot.""" - - -class TransactionSearchResponse(BaseModel): - """Search results for transactions.""" - - data: List[Data] + data_v2: DataV2 diff --git a/src/fragment/types/transaction_update_params.py b/src/fragment/types/transaction_update_params.py new file mode 100644 index 0000000..2f2898a --- /dev/null +++ b/src/fragment/types/transaction_update_params.py @@ -0,0 +1,136 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Iterable +from typing_extensions import Literal, Required, TypeAlias, TypedDict + +__all__ = [ + "TransactionUpdateParams", + "Allocations", + "AllocationsCreate", + "AllocationsCreateUser", + "AllocationsCreateUserID", + "AllocationsCreateUserExternalID", + "AllocationsUpdate", + "Tags", + "TagsCreate", + "TagsDelete", + "TagsSet", + "TagsUpdate", +] + + +class TransactionUpdateParams(TypedDict, total=False): + current_transaction_version: Required[int] + """Current version of the transaction. Must match the stored version.""" + + allocations: Allocations + """Allocation updates.""" + + tags: Tags + """Tag updates.""" + + +class AllocationsCreateUserID(TypedDict, total=False): + id: Required[str] + """FRAGMENT generated unique ID.""" + + +class AllocationsCreateUserExternalID(TypedDict, total=False): + external_id: Required[str] + """User-provided unique ID.""" + + +AllocationsCreateUser: TypeAlias = Union[AllocationsCreateUserID, AllocationsCreateUserExternalID] + + +class AllocationsCreate(TypedDict, total=False): + """An allocation linking a transaction to an invoice.""" + + amount: Required[str] + """ + Allocation amount, as a positive string in the smallest currency unit, such as + cents for USD. + """ + + invoice_id: Required[str] + """Invoice to allocate against.""" + + type: Required[Literal["invoice_payin", "invoice_payout"]] + """Type of allocation.""" + + user: Required[AllocationsCreateUser] + """Identifies a user by `id` or `external_id`.""" + + +class AllocationsUpdate(TypedDict, total=False): + id: Required[str] + """Allocation to update.""" + + amount: Required[str] + """ + Updated allocation amount, as a positive string in the smallest currency unit, + such as cents for USD. + """ + + +class Allocations(TypedDict, total=False): + """Allocation updates.""" + + create: Iterable[AllocationsCreate] + """Allocations to create.""" + + update: Iterable[AllocationsUpdate] + """Allocations to update.""" + + +class TagsCreate(TypedDict, total=False): + """A key-value tag pair for metadata.""" + + key: Required[str] + """Tag key. Must not contain #, /, or :. Max 50 characters.""" + + value: Required[str] + """Tag value. Must not contain #, /, or :. Max 200 characters.""" + + +class TagsDelete(TypedDict, total=False): + key: Required[str] + """Tag key to delete.""" + + +class TagsSet(TypedDict, total=False): + """A key-value tag pair for metadata.""" + + key: Required[str] + """Tag key. Must not contain #, /, or :. Max 50 characters.""" + + value: Required[str] + """Tag value. Must not contain #, /, or :. Max 200 characters.""" + + +class TagsUpdate(TypedDict, total=False): + """A key-value tag pair for metadata.""" + + key: Required[str] + """Tag key. Must not contain #, /, or :. Max 50 characters.""" + + value: Required[str] + """Tag value. Must not contain #, /, or :. Max 200 characters.""" + + +class Tags(TypedDict, total=False): + """Tag updates.""" + + create: Iterable[TagsCreate] + """Tags to create. The tag key must not already exist.""" + + delete: Iterable[TagsDelete] + """Tags to remove.""" + + set: Iterable[TagsSet] + """Tags to set. Creates a new tag or updates an existing tag.""" + + update: Iterable[TagsUpdate] + """Tags to update. The tag key must already exist.""" diff --git a/src/fragment/types/transaction_create_allocations_response.py b/src/fragment/types/transaction_update_response.py similarity index 66% rename from src/fragment/types/transaction_create_allocations_response.py rename to src/fragment/types/transaction_update_response.py index b9887f3..54a3d8a 100644 --- a/src/fragment/types/transaction_create_allocations_response.py +++ b/src/fragment/types/transaction_update_response.py @@ -3,9 +3,9 @@ from .._models import BaseModel from .transaction import Transaction -__all__ = ["TransactionCreateAllocationsResponse"] +__all__ = ["TransactionUpdateResponse"] -class TransactionCreateAllocationsResponse(BaseModel): +class TransactionUpdateResponse(BaseModel): data: Transaction """Transaction object.""" diff --git a/src/fragment/types/user.py b/src/fragment/types/user.py index 7eea5f1..ca34e05 100644 --- a/src/fragment/types/user.py +++ b/src/fragment/types/user.py @@ -6,13 +6,13 @@ class User(BaseModel): - """User object""" + """User object.""" id: str - """Unique user ID""" + """FRAGMENT generated unique ID.""" external_id: str - """External ID for the user""" + """User-provided unique ID.""" role: str - """Role of the user""" + """Name of the user's role.""" diff --git a/src/fragment/types/user_create_params.py b/src/fragment/types/user_create_params.py index 997cb6c..adf66eb 100644 --- a/src/fragment/types/user_create_params.py +++ b/src/fragment/types/user_create_params.py @@ -9,7 +9,7 @@ class UserCreateParams(TypedDict, total=False): external_id: Required[str] - """External ID for the user""" + """User-provided unique ID.""" role: Required[str] - """Role of the user""" + """Name of the role to assign. Must match an existing role.""" diff --git a/src/fragment/types/user_create_response.py b/src/fragment/types/user_create_response.py index 8584137..8a27ae5 100644 --- a/src/fragment/types/user_create_response.py +++ b/src/fragment/types/user_create_response.py @@ -8,4 +8,4 @@ class UserCreateResponse(BaseModel): data: User - """User object""" + """User object.""" diff --git a/src/fragment/types/user_list_response.py b/src/fragment/types/user_list_response.py index 95d7d93..f4a0a11 100644 --- a/src/fragment/types/user_list_response.py +++ b/src/fragment/types/user_list_response.py @@ -9,6 +9,7 @@ class UserListResponse(BaseModel): - """List of users""" + """List of users.""" data: List[User] + """List of users.""" diff --git a/tests/api_resources/test_invoices.py b/tests/api_resources/test_invoices.py index 29c5d56..232f3da 100644 --- a/tests/api_resources/test_invoices.py +++ b/tests/api_resources/test_invoices.py @@ -60,16 +60,16 @@ def test_method_create_with_all_params(self, client: Fragment) -> None: }, "tags": [ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], } ], tags=[ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], ) @@ -190,8 +190,8 @@ def test_method_update_with_all_params(self, client: Fragment) -> None: }, "tags": [ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], } @@ -209,15 +209,21 @@ def test_method_update_with_all_params(self, client: Fragment) -> None: "tags": { "create": [ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], "delete": [{"key": "key"}], + "set": [ + { + "key": "department", + "value": "engineering", + } + ], "update": [ { - "key": "region", - "value": "eu-west-1", + "key": "department", + "value": "engineering", } ], }, @@ -227,15 +233,21 @@ def test_method_update_with_all_params(self, client: Fragment) -> None: tags={ "create": [ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], "delete": [{"key": "key"}], + "set": [ + { + "key": "department", + "value": "engineering", + } + ], "update": [ { - "key": "region", - "value": "eu-west-1", + "key": "department", + "value": "engineering", } ], }, @@ -354,7 +366,6 @@ def test_path_params_list_history(self, client: Fragment) -> None: def test_method_search(self, client: Fragment) -> None: invoice = client.invoices.search( filter={}, - page_info={}, ) assert_matches_type(InvoiceSearchResponse, invoice, path=["response"]) @@ -363,20 +374,21 @@ def test_method_search(self, client: Fragment) -> None: def test_method_search_with_all_params(self, client: Fragment) -> None: invoice = client.invoices.search( filter={ + "status": "open", "tags": { "all": [ { - "key": "env", - "value": "prod", + "key": "department", + "value": "engineering", } ], "any": [ { - "key": "region", - "value": "us-*", + "key": "department", + "value": "eng*", } ], - } + }, }, page_info={ "after": "after", @@ -390,7 +402,6 @@ def test_method_search_with_all_params(self, client: Fragment) -> None: def test_raw_response_search(self, client: Fragment) -> None: response = client.invoices.with_raw_response.search( filter={}, - page_info={}, ) assert response.is_closed is True @@ -403,7 +414,6 @@ def test_raw_response_search(self, client: Fragment) -> None: def test_streaming_response_search(self, client: Fragment) -> None: with client.invoices.with_streaming_response.search( filter={}, - page_info={}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -455,16 +465,16 @@ async def test_method_create_with_all_params(self, async_client: AsyncFragment) }, "tags": [ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], } ], tags=[ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], ) @@ -585,8 +595,8 @@ async def test_method_update_with_all_params(self, async_client: AsyncFragment) }, "tags": [ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], } @@ -604,15 +614,21 @@ async def test_method_update_with_all_params(self, async_client: AsyncFragment) "tags": { "create": [ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], "delete": [{"key": "key"}], + "set": [ + { + "key": "department", + "value": "engineering", + } + ], "update": [ { - "key": "region", - "value": "eu-west-1", + "key": "department", + "value": "engineering", } ], }, @@ -622,15 +638,21 @@ async def test_method_update_with_all_params(self, async_client: AsyncFragment) tags={ "create": [ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], "delete": [{"key": "key"}], + "set": [ + { + "key": "department", + "value": "engineering", + } + ], "update": [ { - "key": "region", - "value": "eu-west-1", + "key": "department", + "value": "engineering", } ], }, @@ -749,7 +771,6 @@ async def test_path_params_list_history(self, async_client: AsyncFragment) -> No async def test_method_search(self, async_client: AsyncFragment) -> None: invoice = await async_client.invoices.search( filter={}, - page_info={}, ) assert_matches_type(InvoiceSearchResponse, invoice, path=["response"]) @@ -758,20 +779,21 @@ async def test_method_search(self, async_client: AsyncFragment) -> None: async def test_method_search_with_all_params(self, async_client: AsyncFragment) -> None: invoice = await async_client.invoices.search( filter={ + "status": "open", "tags": { "all": [ { - "key": "env", - "value": "prod", + "key": "department", + "value": "engineering", } ], "any": [ { - "key": "region", - "value": "us-*", + "key": "department", + "value": "eng*", } ], - } + }, }, page_info={ "after": "after", @@ -785,7 +807,6 @@ async def test_method_search_with_all_params(self, async_client: AsyncFragment) async def test_raw_response_search(self, async_client: AsyncFragment) -> None: response = await async_client.invoices.with_raw_response.search( filter={}, - page_info={}, ) assert response.is_closed is True @@ -798,7 +819,6 @@ async def test_raw_response_search(self, async_client: AsyncFragment) -> None: async def test_streaming_response_search(self, async_client: AsyncFragment) -> None: async with async_client.invoices.with_streaming_response.search( filter={}, - page_info={}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/test_transactions.py b/tests/api_resources/test_transactions.py index 2bfb29f..c7fa19b 100644 --- a/tests/api_resources/test_transactions.py +++ b/tests/api_resources/test_transactions.py @@ -13,9 +13,9 @@ TransactionListResponse, TransactionCreateResponse, TransactionSearchResponse, + TransactionUpdateResponse, TransactionRetrieveResponse, TransactionListHistoryResponse, - TransactionCreateAllocationsResponse, TransactionSearchAllocationsResponse, ) from fragment._utils import parse_datetime @@ -42,7 +42,7 @@ def test_method_create(self, client: Fragment) -> None: amount="-1000", currency="USD", external_id="bank_txn_123", - posted=parse_datetime("2026-02-12T00:00:00.000Z"), + posted=parse_datetime("2024-01-13T00:00:00Z"), ) assert_matches_type(TransactionCreateResponse, transaction, path=["response"]) @@ -65,11 +65,11 @@ def test_method_create_with_all_params(self, client: Fragment) -> None: amount="-1000", currency="USD", external_id="bank_txn_123", - posted=parse_datetime("2026-02-12T00:00:00.000Z"), + posted=parse_datetime("2024-01-13T00:00:00Z"), tags=[ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], ) @@ -91,7 +91,7 @@ def test_raw_response_create(self, client: Fragment) -> None: amount="-1000", currency="USD", external_id="bank_txn_123", - posted=parse_datetime("2026-02-12T00:00:00.000Z"), + posted=parse_datetime("2024-01-13T00:00:00Z"), ) assert response.is_closed is True @@ -115,7 +115,7 @@ def test_streaming_response_create(self, client: Fragment) -> None: amount="-1000", currency="USD", external_id="bank_txn_123", - posted=parse_datetime("2026-02-12T00:00:00.000Z"), + posted=parse_datetime("2024-01-13T00:00:00Z"), ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -169,123 +169,133 @@ def test_path_params_retrieve(self, client: Fragment) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_method_list(self, client: Fragment) -> None: - transaction = client.transactions.list() - assert_matches_type(TransactionListResponse, transaction, path=["response"]) + def test_method_update(self, client: Fragment) -> None: + transaction = client.transactions.update( + transaction_ref="txn_abc123", + current_transaction_version=0, + ) + assert_matches_type(TransactionUpdateResponse, transaction, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_method_list_with_all_params(self, client: Fragment) -> None: - transaction = client.transactions.list( - account="ext_account_YWJjMTIz", - reconciliation_status="reconciled", + def test_method_update_with_all_params(self, client: Fragment) -> None: + transaction = client.transactions.update( + transaction_ref="txn_abc123", + current_transaction_version=0, + allocations={ + "create": [ + { + "amount": "1000", + "invoice_id": "inv_abc123", + "type": "invoice_payin", + "user": {"id": "user_abc123"}, + } + ], + "update": [ + { + "id": "alloc_abc123", + "amount": "2000", + } + ], + }, + tags={ + "create": [ + { + "key": "department", + "value": "engineering", + } + ], + "delete": [{"key": "key"}], + "set": [ + { + "key": "department", + "value": "engineering", + } + ], + "update": [ + { + "key": "department", + "value": "engineering", + } + ], + }, ) - assert_matches_type(TransactionListResponse, transaction, path=["response"]) + assert_matches_type(TransactionUpdateResponse, transaction, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_raw_response_list(self, client: Fragment) -> None: - response = client.transactions.with_raw_response.list() + def test_raw_response_update(self, client: Fragment) -> None: + response = client.transactions.with_raw_response.update( + transaction_ref="txn_abc123", + current_transaction_version=0, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" transaction = response.parse() - assert_matches_type(TransactionListResponse, transaction, path=["response"]) + assert_matches_type(TransactionUpdateResponse, transaction, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_streaming_response_list(self, client: Fragment) -> None: - with client.transactions.with_streaming_response.list() as response: + def test_streaming_response_update(self, client: Fragment) -> None: + with client.transactions.with_streaming_response.update( + transaction_ref="txn_abc123", + current_transaction_version=0, + ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" transaction = response.parse() - assert_matches_type(TransactionListResponse, transaction, path=["response"]) + assert_matches_type(TransactionUpdateResponse, transaction, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_method_create_allocations(self, client: Fragment) -> None: - transaction = client.transactions.create_allocations( - transaction_ref="txn_abc123", - allocation_updates=[ - { - "amount": "1000", - "invoice_id": "inv_abc123", - "op": "add", - "type": "invoice_payin", - "user": {"id": "user_abc123"}, - } - ], - version=0, - ) - assert_matches_type(TransactionCreateAllocationsResponse, transaction, path=["response"]) + def test_path_params_update(self, client: Fragment) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `transaction_ref` but received ''"): + client.transactions.with_raw_response.update( + transaction_ref="", + current_transaction_version=0, + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_raw_response_create_allocations(self, client: Fragment) -> None: - response = client.transactions.with_raw_response.create_allocations( - transaction_ref="txn_abc123", - allocation_updates=[ - { - "amount": "1000", - "invoice_id": "inv_abc123", - "op": "add", - "type": "invoice_payin", - "user": {"id": "user_abc123"}, - } - ], - version=0, + def test_method_list(self, client: Fragment) -> None: + transaction = client.transactions.list() + assert_matches_type(TransactionListResponse, transaction, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Fragment) -> None: + transaction = client.transactions.list( + account="ext_account_YWJjMTIz", + reconciliation_status="reconciled", ) + assert_matches_type(TransactionListResponse, transaction, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Fragment) -> None: + response = client.transactions.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" transaction = response.parse() - assert_matches_type(TransactionCreateAllocationsResponse, transaction, path=["response"]) + assert_matches_type(TransactionListResponse, transaction, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_streaming_response_create_allocations(self, client: Fragment) -> None: - with client.transactions.with_streaming_response.create_allocations( - transaction_ref="txn_abc123", - allocation_updates=[ - { - "amount": "1000", - "invoice_id": "inv_abc123", - "op": "add", - "type": "invoice_payin", - "user": {"id": "user_abc123"}, - } - ], - version=0, - ) as response: + def test_streaming_response_list(self, client: Fragment) -> None: + with client.transactions.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" transaction = response.parse() - assert_matches_type(TransactionCreateAllocationsResponse, transaction, path=["response"]) + assert_matches_type(TransactionListResponse, transaction, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_create_allocations(self, client: Fragment) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `transaction_ref` but received ''"): - client.transactions.with_raw_response.create_allocations( - transaction_ref="", - allocation_updates=[ - { - "amount": "1000", - "invoice_id": "inv_abc123", - "op": "add", - "type": "invoice_payin", - "user": {"id": "user_abc123"}, - } - ], - version=0, - ) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list_history(self, client: Fragment) -> None: @@ -332,7 +342,42 @@ def test_path_params_list_history(self, client: Fragment) -> None: @parametrize def test_method_search(self, client: Fragment) -> None: transaction = client.transactions.search( - filter={"account": {"any": [{}]}}, + filter={}, + ) + assert_matches_type(TransactionSearchResponse, transaction, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_search_with_all_params(self, client: Fragment) -> None: + transaction = client.transactions.search( + filter={ + "account": { + "any": [ + { + "id": "ext_account_YWJjMTIz", + "external_id": "acct_external_123", + } + ] + }, + "tags": { + "all": [ + { + "key": "department", + "value": "engineering", + } + ], + "any": [ + { + "key": "department", + "value": "eng*", + } + ], + }, + }, + page_info={ + "after": "after", + "limit": 20, + }, ) assert_matches_type(TransactionSearchResponse, transaction, path=["response"]) @@ -340,7 +385,7 @@ def test_method_search(self, client: Fragment) -> None: @parametrize def test_raw_response_search(self, client: Fragment) -> None: response = client.transactions.with_raw_response.search( - filter={"account": {"any": [{}]}}, + filter={}, ) assert response.is_closed is True @@ -352,7 +397,7 @@ def test_raw_response_search(self, client: Fragment) -> None: @parametrize def test_streaming_response_search(self, client: Fragment) -> None: with client.transactions.with_streaming_response.search( - filter={"account": {"any": [{}]}}, + filter={}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -418,7 +463,7 @@ async def test_method_create(self, async_client: AsyncFragment) -> None: amount="-1000", currency="USD", external_id="bank_txn_123", - posted=parse_datetime("2026-02-12T00:00:00.000Z"), + posted=parse_datetime("2024-01-13T00:00:00Z"), ) assert_matches_type(TransactionCreateResponse, transaction, path=["response"]) @@ -441,11 +486,11 @@ async def test_method_create_with_all_params(self, async_client: AsyncFragment) amount="-1000", currency="USD", external_id="bank_txn_123", - posted=parse_datetime("2026-02-12T00:00:00.000Z"), + posted=parse_datetime("2024-01-13T00:00:00Z"), tags=[ { - "key": "region", - "value": "us-east", + "key": "department", + "value": "engineering", } ], ) @@ -467,7 +512,7 @@ async def test_raw_response_create(self, async_client: AsyncFragment) -> None: amount="-1000", currency="USD", external_id="bank_txn_123", - posted=parse_datetime("2026-02-12T00:00:00.000Z"), + posted=parse_datetime("2024-01-13T00:00:00Z"), ) assert response.is_closed is True @@ -491,7 +536,7 @@ async def test_streaming_response_create(self, async_client: AsyncFragment) -> N amount="-1000", currency="USD", external_id="bank_txn_123", - posted=parse_datetime("2026-02-12T00:00:00.000Z"), + posted=parse_datetime("2024-01-13T00:00:00Z"), ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -545,123 +590,133 @@ async def test_path_params_retrieve(self, async_client: AsyncFragment) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_list(self, async_client: AsyncFragment) -> None: - transaction = await async_client.transactions.list() - assert_matches_type(TransactionListResponse, transaction, path=["response"]) + async def test_method_update(self, async_client: AsyncFragment) -> None: + transaction = await async_client.transactions.update( + transaction_ref="txn_abc123", + current_transaction_version=0, + ) + assert_matches_type(TransactionUpdateResponse, transaction, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncFragment) -> None: - transaction = await async_client.transactions.list( - account="ext_account_YWJjMTIz", - reconciliation_status="reconciled", + async def test_method_update_with_all_params(self, async_client: AsyncFragment) -> None: + transaction = await async_client.transactions.update( + transaction_ref="txn_abc123", + current_transaction_version=0, + allocations={ + "create": [ + { + "amount": "1000", + "invoice_id": "inv_abc123", + "type": "invoice_payin", + "user": {"id": "user_abc123"}, + } + ], + "update": [ + { + "id": "alloc_abc123", + "amount": "2000", + } + ], + }, + tags={ + "create": [ + { + "key": "department", + "value": "engineering", + } + ], + "delete": [{"key": "key"}], + "set": [ + { + "key": "department", + "value": "engineering", + } + ], + "update": [ + { + "key": "department", + "value": "engineering", + } + ], + }, ) - assert_matches_type(TransactionListResponse, transaction, path=["response"]) + assert_matches_type(TransactionUpdateResponse, transaction, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_list(self, async_client: AsyncFragment) -> None: - response = await async_client.transactions.with_raw_response.list() + async def test_raw_response_update(self, async_client: AsyncFragment) -> None: + response = await async_client.transactions.with_raw_response.update( + transaction_ref="txn_abc123", + current_transaction_version=0, + ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" transaction = await response.parse() - assert_matches_type(TransactionListResponse, transaction, path=["response"]) + assert_matches_type(TransactionUpdateResponse, transaction, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_list(self, async_client: AsyncFragment) -> None: - async with async_client.transactions.with_streaming_response.list() as response: + async def test_streaming_response_update(self, async_client: AsyncFragment) -> None: + async with async_client.transactions.with_streaming_response.update( + transaction_ref="txn_abc123", + current_transaction_version=0, + ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" transaction = await response.parse() - assert_matches_type(TransactionListResponse, transaction, path=["response"]) + assert_matches_type(TransactionUpdateResponse, transaction, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_create_allocations(self, async_client: AsyncFragment) -> None: - transaction = await async_client.transactions.create_allocations( - transaction_ref="txn_abc123", - allocation_updates=[ - { - "amount": "1000", - "invoice_id": "inv_abc123", - "op": "add", - "type": "invoice_payin", - "user": {"id": "user_abc123"}, - } - ], - version=0, - ) - assert_matches_type(TransactionCreateAllocationsResponse, transaction, path=["response"]) + async def test_path_params_update(self, async_client: AsyncFragment) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `transaction_ref` but received ''"): + await async_client.transactions.with_raw_response.update( + transaction_ref="", + current_transaction_version=0, + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_create_allocations(self, async_client: AsyncFragment) -> None: - response = await async_client.transactions.with_raw_response.create_allocations( - transaction_ref="txn_abc123", - allocation_updates=[ - { - "amount": "1000", - "invoice_id": "inv_abc123", - "op": "add", - "type": "invoice_payin", - "user": {"id": "user_abc123"}, - } - ], - version=0, + async def test_method_list(self, async_client: AsyncFragment) -> None: + transaction = await async_client.transactions.list() + assert_matches_type(TransactionListResponse, transaction, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncFragment) -> None: + transaction = await async_client.transactions.list( + account="ext_account_YWJjMTIz", + reconciliation_status="reconciled", ) + assert_matches_type(TransactionListResponse, transaction, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncFragment) -> None: + response = await async_client.transactions.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" transaction = await response.parse() - assert_matches_type(TransactionCreateAllocationsResponse, transaction, path=["response"]) + assert_matches_type(TransactionListResponse, transaction, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_create_allocations(self, async_client: AsyncFragment) -> None: - async with async_client.transactions.with_streaming_response.create_allocations( - transaction_ref="txn_abc123", - allocation_updates=[ - { - "amount": "1000", - "invoice_id": "inv_abc123", - "op": "add", - "type": "invoice_payin", - "user": {"id": "user_abc123"}, - } - ], - version=0, - ) as response: + async def test_streaming_response_list(self, async_client: AsyncFragment) -> None: + async with async_client.transactions.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" transaction = await response.parse() - assert_matches_type(TransactionCreateAllocationsResponse, transaction, path=["response"]) + assert_matches_type(TransactionListResponse, transaction, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_create_allocations(self, async_client: AsyncFragment) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `transaction_ref` but received ''"): - await async_client.transactions.with_raw_response.create_allocations( - transaction_ref="", - allocation_updates=[ - { - "amount": "1000", - "invoice_id": "inv_abc123", - "op": "add", - "type": "invoice_payin", - "user": {"id": "user_abc123"}, - } - ], - version=0, - ) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list_history(self, async_client: AsyncFragment) -> None: @@ -708,7 +763,42 @@ async def test_path_params_list_history(self, async_client: AsyncFragment) -> No @parametrize async def test_method_search(self, async_client: AsyncFragment) -> None: transaction = await async_client.transactions.search( - filter={"account": {"any": [{}]}}, + filter={}, + ) + assert_matches_type(TransactionSearchResponse, transaction, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_search_with_all_params(self, async_client: AsyncFragment) -> None: + transaction = await async_client.transactions.search( + filter={ + "account": { + "any": [ + { + "id": "ext_account_YWJjMTIz", + "external_id": "acct_external_123", + } + ] + }, + "tags": { + "all": [ + { + "key": "department", + "value": "engineering", + } + ], + "any": [ + { + "key": "department", + "value": "eng*", + } + ], + }, + }, + page_info={ + "after": "after", + "limit": 20, + }, ) assert_matches_type(TransactionSearchResponse, transaction, path=["response"]) @@ -716,7 +806,7 @@ async def test_method_search(self, async_client: AsyncFragment) -> None: @parametrize async def test_raw_response_search(self, async_client: AsyncFragment) -> None: response = await async_client.transactions.with_raw_response.search( - filter={"account": {"any": [{}]}}, + filter={}, ) assert response.is_closed is True @@ -728,7 +818,7 @@ async def test_raw_response_search(self, async_client: AsyncFragment) -> None: @parametrize async def test_streaming_response_search(self, async_client: AsyncFragment) -> None: async with async_client.transactions.with_streaming_response.search( - filter={"account": {"any": [{}]}}, + filter={}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/test_client.py b/tests/test_client.py index 10cfb2e..3bf1432 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -458,6 +458,30 @@ def test_default_query_option(self) -> None: client.close() + def test_hardcoded_query_params_in_url(self, client: Fragment) -> None: + request = client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: Fragment) -> None: request = client._build_request( FinalRequestOptions( @@ -1423,6 +1447,30 @@ async def test_default_query_option(self) -> None: await client.close() + async def test_hardcoded_query_params_in_url(self, async_client: AsyncFragment) -> None: + request = async_client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/foo?beta=true", + params={"limit": "10", "page": "abc"}, + ) + ) + url = httpx.URL(request.url) + assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} + + request = async_client._build_request( + FinalRequestOptions( + method="get", + url="/files/a%2Fb?beta=true", + params={"limit": "10"}, + ) + ) + assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" + def test_request_extra_json(self, client: Fragment) -> None: request = client._build_request( FinalRequestOptions( diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 783e4c7..3a59a56 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -35,6 +35,15 @@ def test_multiple_files() -> None: assert query == {"documents": [{}, {}]} +def test_top_level_file_array() -> None: + query = {"files": [b"file one", b"file two"], "title": "hello"} + assert extract_files(query, paths=[["files", ""]]) == [ + ("files[]", b"file one"), + ("files[]", b"file two"), + ] + assert query == {"title": "hello"} + + @pytest.mark.parametrize( "query,paths,expected", [