diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a8072d1..99550732 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/lithic-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@v6 @@ -38,7 +38,7 @@ jobs: run: ./scripts/lint build: - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') timeout-minutes: 10 name: build permissions: @@ -107,7 +107,7 @@ jobs: timeout-minutes: 10 name: examples runs-on: ${{ github.repository == 'stainless-sdks/lithic-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.repository == 'lithic-com/lithic-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) + if: github.repository == 'lithic-com/lithic-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@v6 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 486a203f..4bab9967 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.120.0" + ".": "0.121.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index b44dee87..4160e915 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 189 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-17c04dd1b0508b380c21e3acc3d4cd1e86b590f81d14fa26d1973b236f660e38.yml -openapi_spec_hash: f8ddee07358d2c938450a6889fbf7940 -config_hash: edbdfefeb0d3d927c2f9fe3402793215 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-df28ee30a3bd4fa595befc2048216e1ee1d3845fcfcf179c1c694ba58fd5e4ed.yml +openapi_spec_hash: 79bfc19d85c7f03754684d794653e333 +config_hash: 5eca052bb23d273fa970eac3127dd919 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7430bae7..c7fb64e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,39 @@ # Changelog +## 0.121.0 (2026-04-10) + +Full Changelog: [v0.120.0...v0.121.0](https://github.com/lithic-com/lithic-python/compare/v0.120.0...v0.121.0) + +### Features + +* **api:** add decline count attributes to auth_rules conditions ([c511d14](https://github.com/lithic-com/lithic-python/commit/c511d14d11ca9c7d37fb549cb36ca3cba4661224)) +* **api:** add INTERCHANGE/CHARGEBACK/PROVISIONAL_CREDIT_ACCOUNT account types ([aa96cd4](https://github.com/lithic-com/lithic-python/commit/aa96cd46ed483528438520ffa337b9dbdfa85e45)) +* **api:** add override_company_name parameter to payment create method ([babec29](https://github.com/lithic-com/lithic-python/commit/babec2956fc1cea2f2a7568f7229be0973f763f6)) +* **api:** add statement_totals field to Statement model ([3b035bc](https://github.com/lithic-com/lithic-python/commit/3b035bce611c86716f0f837e11a590384c94442e)) +* **api:** add transaction_token field to auth_rules example models ([ce41be2](https://github.com/lithic-com/lithic-python/commit/ce41be23c7b6a638e387598ced8ebb31d9696cb9)) +* **api:** add transaction_token field to auth_rules result types ([25fcd02](https://github.com/lithic-com/lithic-python/commit/25fcd02a8982d74d39761c25eaeee897d19e7601)) +* **internal:** implement indices array format for query and form serialization ([bef46fb](https://github.com/lithic-com/lithic-python/commit/bef46fbe5eacffefedb37a7677753e877da3c922)) + + +### Bug Fixes + +* **api:** [breaking] remove approved/decision/challenged/declined fields from auth_rules report_stats ([b81fa5c](https://github.com/lithic-com/lithic-python/commit/b81fa5c76b79066d1a00fdf4c896213542277607)) +* **client:** preserve hardcoded query params when merging with user params ([89aced4](https://github.com/lithic-com/lithic-python/commit/89aced4c87b0777be00f82621e50077905bff9d8)) +* ensure file data are only sent as 1 parameter ([6f796aa](https://github.com/lithic-com/lithic-python/commit/6f796aae3a23a29bf4a17e2462a94dc502d5303e)) +* **types:** make credit_product_token optional in Statement ([6caf4c4](https://github.com/lithic-com/lithic-python/commit/6caf4c4065ffb59f6e285f72c1d0f4b5c8713249)) +* **types:** make fields required, remove hostname in card authorization approval webhook ([80c1bcc](https://github.com/lithic-com/lithic-python/commit/80c1bccf3efd889135833d481db58ca7743464c3)) +* **types:** remove INTERCHANGE and CHARGEBACK from financial account types ([5567809](https://github.com/lithic-com/lithic-python/commit/55678093ad91356470a2e7dc30bcb9ec1069263d)) + + +### Chores + +* **ci:** skip lint on metadata-only changes ([7d73b7b](https://github.com/lithic-com/lithic-python/commit/7d73b7b0775f2e4f9fe6cd78f5bbf528b93804ab)) + + +### Documentation + +* **api:** update nature_of_business and qr_code_url parameter descriptions ([7514c59](https://github.com/lithic-com/lithic-python/commit/7514c5966cd9b4a84d221aadffe3ef02c7fa8814)) + ## 0.120.0 (2026-03-23) Full Changelog: [v0.119.0...v0.120.0](https://github.com/lithic-com/lithic-python/compare/v0.119.0...v0.120.0) diff --git a/pyproject.toml b/pyproject.toml index 1a227b5a..3eb30e09 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lithic" -version = "0.120.0" +version = "0.121.0" description = "The official Python library for the lithic API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/lithic/_base_client.py b/src/lithic/_base_client.py index e992a795..211e991e 100644 --- a/src/lithic/_base_client.py +++ b/src/lithic/_base_client.py @@ -541,6 +541,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/lithic/_qs.py b/src/lithic/_qs.py index ada6fd3f..de8c99bc 100644 --- a/src/lithic/_qs.py +++ b/src/lithic/_qs.py @@ -101,7 +101,10 @@ def _stringify_item( items.extend(self._stringify_item(key, item, opts)) return items elif array_format == "indices": - raise NotImplementedError("The array indices format is not supported yet") + items = [] + for i, item in enumerate(value): + items.extend(self._stringify_item(f"{key}[{i}]", item, opts)) + return items elif array_format == "brackets": items = [] key = key + "[]" diff --git a/src/lithic/_utils/_utils.py b/src/lithic/_utils/_utils.py index eec7f4a1..63b8cd60 100644 --- a/src/lithic/_utils/_utils.py +++ b/src/lithic/_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/lithic/_version.py b/src/lithic/_version.py index 63c609e4..c5edd576 100644 --- a/src/lithic/_version.py +++ b/src/lithic/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "lithic" -__version__ = "0.120.0" # x-release-please-version +__version__ = "0.121.0" # x-release-please-version diff --git a/src/lithic/resources/card_bulk_orders.py b/src/lithic/resources/card_bulk_orders.py index 40c9d132..7d4db098 100644 --- a/src/lithic/resources/card_bulk_orders.py +++ b/src/lithic/resources/card_bulk_orders.py @@ -47,7 +47,7 @@ def create( *, customer_product_id: str, shipping_address: object, - shipping_method: Literal["BULK_EXPEDITED"], + shipping_method: Literal["BULK_EXPEDITED", "BULK_PRIORITY", "BULK_2_DAY", "BULK_EXPRESS"], # 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, @@ -55,14 +55,13 @@ def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CardBulkOrder: - """Create a new bulk order for physical card shipments **[BETA]**. + """Create a new bulk order for physical card shipments. - Cards can be - added to the order via the POST /v1/cards endpoint by specifying the - bulk_order_token. Lock the order via PATCH - /v1/card_bulk_orders/{bulk_order_token} to prepare for shipment. Please work - with your Customer Success Manager and card personalization bureau to ensure - bulk shipping is supported for your program. + Cards can be added to the + order via the POST /v1/cards endpoint by specifying the bulk_order_token. Lock + the order via PATCH /v1/card_bulk_orders/{bulk_order_token} to prepare for + shipment. Please work with your Customer Success Manager and card + personalization bureau to ensure bulk shipping is supported for your program. Args: customer_product_id: Customer-specified product configuration for physical card manufacturing. This @@ -70,7 +69,8 @@ def create( shipping_address: Shipping address for all cards in this bulk order - shipping_method: Shipping method for all cards in this bulk order + shipping_method: Shipping method for all cards in this bulk order. BULK_PRIORITY, BULK_2_DAY, and + BULK_EXPRESS are only available with Perfect Plastic Printing extra_headers: Send extra headers @@ -108,7 +108,7 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CardBulkOrder: """ - Retrieve a specific bulk order by token **[BETA]** + Retrieve a specific bulk order by token Args: extra_headers: Send extra headers @@ -141,10 +141,10 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CardBulkOrder: - """Update a bulk order **[BETA]**. + """Update a bulk order. - Primarily used to lock the order, preventing - additional cards from being added + Primarily used to lock the order, preventing additional + cards from being added Args: status: Status to update the bulk order to. Use LOCKED to finalize the order @@ -184,7 +184,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[CardBulkOrder]: """ - List bulk orders for physical card shipments **[BETA]** + List bulk orders for physical card shipments Args: begin: Date string in RFC 3339 format. Only entries created after the specified time @@ -257,7 +257,7 @@ async def create( *, customer_product_id: str, shipping_address: object, - shipping_method: Literal["BULK_EXPEDITED"], + shipping_method: Literal["BULK_EXPEDITED", "BULK_PRIORITY", "BULK_2_DAY", "BULK_EXPRESS"], # 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, @@ -265,14 +265,13 @@ async def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CardBulkOrder: - """Create a new bulk order for physical card shipments **[BETA]**. + """Create a new bulk order for physical card shipments. - Cards can be - added to the order via the POST /v1/cards endpoint by specifying the - bulk_order_token. Lock the order via PATCH - /v1/card_bulk_orders/{bulk_order_token} to prepare for shipment. Please work - with your Customer Success Manager and card personalization bureau to ensure - bulk shipping is supported for your program. + Cards can be added to the + order via the POST /v1/cards endpoint by specifying the bulk_order_token. Lock + the order via PATCH /v1/card_bulk_orders/{bulk_order_token} to prepare for + shipment. Please work with your Customer Success Manager and card + personalization bureau to ensure bulk shipping is supported for your program. Args: customer_product_id: Customer-specified product configuration for physical card manufacturing. This @@ -280,7 +279,8 @@ async def create( shipping_address: Shipping address for all cards in this bulk order - shipping_method: Shipping method for all cards in this bulk order + shipping_method: Shipping method for all cards in this bulk order. BULK_PRIORITY, BULK_2_DAY, and + BULK_EXPRESS are only available with Perfect Plastic Printing extra_headers: Send extra headers @@ -318,7 +318,7 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CardBulkOrder: """ - Retrieve a specific bulk order by token **[BETA]** + Retrieve a specific bulk order by token Args: extra_headers: Send extra headers @@ -351,10 +351,10 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CardBulkOrder: - """Update a bulk order **[BETA]**. + """Update a bulk order. - Primarily used to lock the order, preventing - additional cards from being added + Primarily used to lock the order, preventing additional + cards from being added Args: status: Status to update the bulk order to. Use LOCKED to finalize the order @@ -396,7 +396,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[CardBulkOrder, AsyncCursorPage[CardBulkOrder]]: """ - List bulk orders for physical card shipments **[BETA]** + List bulk orders for physical card shipments Args: begin: Date string in RFC 3339 format. Only entries created after the specified time diff --git a/src/lithic/resources/cards/cards.py b/src/lithic/resources/cards/cards.py index e627f240..8b4e7959 100644 --- a/src/lithic/resources/cards/cards.py +++ b/src/lithic/resources/cards/cards.py @@ -124,7 +124,7 @@ def create( | Omit = omit, shipping_address: ShippingAddress | Omit = omit, shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" + "2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" ] | Omit = omit, spend_limit: int | Omit = omit, @@ -254,7 +254,8 @@ def create( tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. spend_limit: Amount (in cents) to limit approved authorizations (e.g. 100000 would be a $1,000 limit). Transaction requests above the spend limit will be declined. Note @@ -595,7 +596,7 @@ def convert_physical( carrier: Carrier | Omit = omit, product_id: str | Omit = omit, shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" + "2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -641,7 +642,8 @@ def convert_physical( tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. extra_headers: Send extra headers @@ -940,7 +942,7 @@ def reissue( product_id: str | Omit = omit, shipping_address: ShippingAddress | Omit = omit, shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" + "2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -981,7 +983,8 @@ def reissue( tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. extra_headers: Send extra headers @@ -1020,7 +1023,7 @@ def renew( exp_year: str | Omit = omit, product_id: str | Omit = omit, shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" + "2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1071,7 +1074,8 @@ def renew( tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. extra_headers: Send extra headers @@ -1306,7 +1310,7 @@ async def create( | Omit = omit, shipping_address: ShippingAddress | Omit = omit, shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" + "2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" ] | Omit = omit, spend_limit: int | Omit = omit, @@ -1436,7 +1440,8 @@ async def create( tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. spend_limit: Amount (in cents) to limit approved authorizations (e.g. 100000 would be a $1,000 limit). Transaction requests above the spend limit will be declined. Note @@ -1777,7 +1782,7 @@ async def convert_physical( carrier: Carrier | Omit = omit, product_id: str | Omit = omit, shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" + "2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1823,7 +1828,8 @@ async def convert_physical( tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. extra_headers: Send extra headers @@ -2122,7 +2128,7 @@ async def reissue( product_id: str | Omit = omit, shipping_address: ShippingAddress | Omit = omit, shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" + "2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -2163,7 +2169,8 @@ async def reissue( tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. extra_headers: Send extra headers @@ -2202,7 +2209,7 @@ async def renew( exp_year: str | Omit = omit, product_id: str | Omit = omit, shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" + "2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -2253,7 +2260,8 @@ async def renew( tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. extra_headers: Send extra headers diff --git a/src/lithic/types/auth_rules/backtest_stats.py b/src/lithic/types/auth_rules/backtest_stats.py index 19b66503..304ecf85 100644 --- a/src/lithic/types/auth_rules/backtest_stats.py +++ b/src/lithic/types/auth_rules/backtest_stats.py @@ -19,6 +19,9 @@ class Example(BaseModel): timestamp: Optional[datetime] = None """The timestamp of the event.""" + transaction_token: Optional[str] = None + """The token of the transaction associated with the event""" + class BacktestStats(BaseModel): approved: Optional[int] = None diff --git a/src/lithic/types/auth_rules/conditional_authorization_action_parameters.py b/src/lithic/types/auth_rules/conditional_authorization_action_parameters.py index 6606f238..e2a4fb93 100644 --- a/src/lithic/types/auth_rules/conditional_authorization_action_parameters.py +++ b/src/lithic/types/auth_rules/conditional_authorization_action_parameters.py @@ -25,6 +25,9 @@ class Condition(BaseModel): "CARD_TRANSACTION_COUNT_15M", "CARD_TRANSACTION_COUNT_1H", "CARD_TRANSACTION_COUNT_24H", + "CARD_DECLINE_COUNT_15M", + "CARD_DECLINE_COUNT_1H", + "CARD_DECLINE_COUNT_24H", "CARD_STATE", "PIN_ENTERED", "PIN_STATUS", @@ -75,6 +78,12 @@ class Condition(BaseModel): trailing hour up and until the authorization. - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the trailing 24 hours up and until the authorization. + - `CARD_DECLINE_COUNT_15M`: The number of declined transactions on the card in + the trailing 15 minutes before the authorization. + - `CARD_DECLINE_COUNT_1H`: The number of declined transactions on the card in + the trailing hour up and until the authorization. + - `CARD_DECLINE_COUNT_24H`: The number of declined transactions on the card in + the trailing 24 hours up and until the authorization. - `CARD_STATE`: The current state of the card associated with the transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. diff --git a/src/lithic/types/auth_rules/conditional_authorization_action_parameters_param.py b/src/lithic/types/auth_rules/conditional_authorization_action_parameters_param.py index a04adbc4..11a1c220 100644 --- a/src/lithic/types/auth_rules/conditional_authorization_action_parameters_param.py +++ b/src/lithic/types/auth_rules/conditional_authorization_action_parameters_param.py @@ -28,6 +28,9 @@ class Condition(TypedDict, total=False): "CARD_TRANSACTION_COUNT_15M", "CARD_TRANSACTION_COUNT_1H", "CARD_TRANSACTION_COUNT_24H", + "CARD_DECLINE_COUNT_15M", + "CARD_DECLINE_COUNT_1H", + "CARD_DECLINE_COUNT_24H", "CARD_STATE", "PIN_ENTERED", "PIN_STATUS", @@ -79,6 +82,12 @@ class Condition(TypedDict, total=False): trailing hour up and until the authorization. - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the trailing 24 hours up and until the authorization. + - `CARD_DECLINE_COUNT_15M`: The number of declined transactions on the card in + the trailing 15 minutes before the authorization. + - `CARD_DECLINE_COUNT_1H`: The number of declined transactions on the card in + the trailing hour up and until the authorization. + - `CARD_DECLINE_COUNT_24H`: The number of declined transactions on the card in + the trailing 24 hours up and until the authorization. - `CARD_STATE`: The current state of the card associated with the transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. diff --git a/src/lithic/types/auth_rules/report_stats.py b/src/lithic/types/auth_rules/report_stats.py index a0796364..d8a1bdb7 100644 --- a/src/lithic/types/auth_rules/report_stats.py +++ b/src/lithic/types/auth_rules/report_stats.py @@ -243,52 +243,33 @@ class ExampleActionReturnAction(BaseModel): class Example(BaseModel): - actions: Optional[List[ExampleAction]] = None - """The actions taken by the rule for this event.""" + actions: List[ExampleAction] + """The actions taken by this version for this event.""" - approved: Optional[bool] = None - """Whether the rule would have approved the request.""" - - decision: Optional[Literal["APPROVED", "DECLINED", "CHALLENGED"]] = None - """The decision made by the rule for this event.""" - - event_token: Optional[str] = None + event_token: str """The event token.""" - timestamp: Optional[datetime] = None + timestamp: datetime """The timestamp of the event.""" + transaction_token: Optional[str] = None + """The token of the transaction associated with the event""" + class ReportStats(BaseModel): - action_counts: Optional[Dict[str, int]] = None + action_counts: Dict[str, int] """ A mapping of action types to the number of times that action was returned by - this rule during the relevant period. Actions are the possible outcomes of a + this version during the relevant period. Actions are the possible outcomes of a rule evaluation, such as DECLINE, CHALLENGE, REQUIRE_TFA, etc. In case rule didn't trigger any action, it's counted under NO_ACTION key. """ - approved: Optional[int] = None - """ - The total number of historical transactions approved by this rule during the - relevant period, or the number of transactions that would have been approved if - the rule was evaluated in shadow mode. - """ - - challenged: Optional[int] = None - """ - The total number of historical transactions challenged by this rule during the - relevant period, or the number of transactions that would have been challenged - if the rule was evaluated in shadow mode. Currently applicable only for 3DS Auth - Rules. - """ + examples: List[Example] + """Example events and their outcomes for this version.""" - declined: Optional[int] = None - """ - The total number of historical transactions declined by this rule during the - relevant period, or the number of transactions that would have been declined if - the rule was evaluated in shadow mode. - """ + state: Literal["ACTIVE", "SHADOW", "INACTIVE"] + """The evaluation mode of this version during the reported period.""" - examples: Optional[List[Example]] = None - """Example events and their outcomes.""" + version: int + """The rule version number.""" diff --git a/src/lithic/types/auth_rules/v2_list_results_response.py b/src/lithic/types/auth_rules/v2_list_results_response.py index d53cafb7..7ef3805d 100644 --- a/src/lithic/types/auth_rules/v2_list_results_response.py +++ b/src/lithic/types/auth_rules/v2_list_results_response.py @@ -130,6 +130,9 @@ class AuthorizationResult(BaseModel): rule_version: int """Version of the rule that was evaluated""" + transaction_token: Optional[str] = None + """The token of the transaction that triggered the rule evaluation""" + class Authentication3DsResultAction(BaseModel): type: Literal["DECLINE", "CHALLENGE"] @@ -163,6 +166,9 @@ class Authentication3DSResult(BaseModel): rule_version: int """Version of the rule that was evaluated""" + transaction_token: Optional[str] = None + """The token of the transaction that triggered the rule evaluation""" + class TokenizationResultActionDeclineActionTokenization(BaseModel): type: Literal["DECLINE"] @@ -250,6 +256,9 @@ class TokenizationResult(BaseModel): rule_version: int """Version of the rule that was evaluated""" + transaction_token: Optional[str] = None + """The token of the transaction that triggered the rule evaluation""" + class ACHResultActionApproveActionACH(BaseModel): type: Literal["APPROVE"] @@ -373,5 +382,8 @@ class ACHResult(BaseModel): rule_version: int """Version of the rule that was evaluated""" + transaction_token: Optional[str] = None + """The token of the transaction that triggered the rule evaluation""" + V2ListResultsResponse: TypeAlias = Union[AuthorizationResult, Authentication3DSResult, TokenizationResult, ACHResult] diff --git a/src/lithic/types/auth_rules/v2_retrieve_report_response.py b/src/lithic/types/auth_rules/v2_retrieve_report_response.py index 6e4860ce..5b50fefe 100644 --- a/src/lithic/types/auth_rules/v2_retrieve_report_response.py +++ b/src/lithic/types/auth_rules/v2_retrieve_report_response.py @@ -1,291 +1,19 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import datetime -from typing import Dict, List, Union, Optional -from typing_extensions import Literal, TypeAlias +from typing import List from ..._models import BaseModel from .report_stats import ReportStats -__all__ = [ - "V2RetrieveReportResponse", - "DailyStatistic", - "DailyStatisticVersion", - "DailyStatisticVersionExample", - "DailyStatisticVersionExampleAction", - "DailyStatisticVersionExampleActionDeclineActionAuthorization", - "DailyStatisticVersionExampleActionChallengeActionAuthorization", - "DailyStatisticVersionExampleActionResultAuthentication3DSAction", - "DailyStatisticVersionExampleActionDeclineActionTokenization", - "DailyStatisticVersionExampleActionRequireTfaAction", - "DailyStatisticVersionExampleActionApproveActionACH", - "DailyStatisticVersionExampleActionReturnAction", -] - - -class DailyStatisticVersionExampleActionDeclineActionAuthorization(BaseModel): - code: Literal[ - "ACCOUNT_DAILY_SPEND_LIMIT_EXCEEDED", - "ACCOUNT_DELINQUENT", - "ACCOUNT_INACTIVE", - "ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED", - "ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED", - "ACCOUNT_PAUSED", - "ACCOUNT_UNDER_REVIEW", - "ADDRESS_INCORRECT", - "APPROVED", - "AUTH_RULE_ALLOWED_COUNTRY", - "AUTH_RULE_ALLOWED_MCC", - "AUTH_RULE_BLOCKED_COUNTRY", - "AUTH_RULE_BLOCKED_MCC", - "AUTH_RULE", - "CARD_CLOSED", - "CARD_CRYPTOGRAM_VALIDATION_FAILURE", - "CARD_EXPIRED", - "CARD_EXPIRY_DATE_INCORRECT", - "CARD_INVALID", - "CARD_NOT_ACTIVATED", - "CARD_PAUSED", - "CARD_PIN_INCORRECT", - "CARD_RESTRICTED", - "CARD_SECURITY_CODE_INCORRECT", - "CARD_SPEND_LIMIT_EXCEEDED", - "CONTACT_CARD_ISSUER", - "CUSTOMER_ASA_TIMEOUT", - "CUSTOM_ASA_RESULT", - "DECLINED", - "DO_NOT_HONOR", - "DRIVER_NUMBER_INVALID", - "FORMAT_ERROR", - "INSUFFICIENT_FUNDING_SOURCE_BALANCE", - "INSUFFICIENT_FUNDS", - "LITHIC_SYSTEM_ERROR", - "LITHIC_SYSTEM_RATE_LIMIT", - "MALFORMED_ASA_RESPONSE", - "MERCHANT_INVALID", - "MERCHANT_LOCKED_CARD_ATTEMPTED_ELSEWHERE", - "MERCHANT_NOT_PERMITTED", - "OVER_REVERSAL_ATTEMPTED", - "PIN_BLOCKED", - "PROGRAM_CARD_SPEND_LIMIT_EXCEEDED", - "PROGRAM_SUSPENDED", - "PROGRAM_USAGE_RESTRICTION", - "REVERSAL_UNMATCHED", - "SECURITY_VIOLATION", - "SINGLE_USE_CARD_REATTEMPTED", - "SUSPECTED_FRAUD", - "TRANSACTION_INVALID", - "TRANSACTION_NOT_PERMITTED_TO_ACQUIRER_OR_TERMINAL", - "TRANSACTION_NOT_PERMITTED_TO_ISSUER_OR_CARDHOLDER", - "TRANSACTION_PREVIOUSLY_COMPLETED", - "UNAUTHORIZED_MERCHANT", - "VEHICLE_NUMBER_INVALID", - "CARDHOLDER_CHALLENGED", - "CARDHOLDER_CHALLENGE_FAILED", - ] - """The detailed result code explaining the specific reason for the decline""" - - type: Literal["DECLINE"] - - -class DailyStatisticVersionExampleActionChallengeActionAuthorization(BaseModel): - type: Literal["CHALLENGE"] - - -class DailyStatisticVersionExampleActionResultAuthentication3DSAction(BaseModel): - type: Literal["DECLINE", "CHALLENGE"] - - -class DailyStatisticVersionExampleActionDeclineActionTokenization(BaseModel): - type: Literal["DECLINE"] - """Decline the tokenization request""" - - reason: Optional[ - Literal[ - "ACCOUNT_SCORE_1", - "DEVICE_SCORE_1", - "ALL_WALLET_DECLINE_REASONS_PRESENT", - "WALLET_RECOMMENDED_DECISION_RED", - "CVC_MISMATCH", - "CARD_EXPIRY_MONTH_MISMATCH", - "CARD_EXPIRY_YEAR_MISMATCH", - "CARD_INVALID_STATE", - "CUSTOMER_RED_PATH", - "INVALID_CUSTOMER_RESPONSE", - "NETWORK_FAILURE", - "GENERIC_DECLINE", - "DIGITAL_CARD_ART_REQUIRED", - ] - ] = None - """Reason code for declining the tokenization request""" - - -class DailyStatisticVersionExampleActionRequireTfaAction(BaseModel): - type: Literal["REQUIRE_TFA"] - """Require two-factor authentication for the tokenization request""" - - reason: Optional[ - Literal[ - "WALLET_RECOMMENDED_TFA", - "SUSPICIOUS_ACTIVITY", - "DEVICE_RECENTLY_LOST", - "TOO_MANY_RECENT_ATTEMPTS", - "TOO_MANY_RECENT_TOKENS", - "TOO_MANY_DIFFERENT_CARDHOLDERS", - "OUTSIDE_HOME_TERRITORY", - "HAS_SUSPENDED_TOKENS", - "HIGH_RISK", - "ACCOUNT_SCORE_LOW", - "DEVICE_SCORE_LOW", - "CARD_STATE_TFA", - "HARDCODED_TFA", - "CUSTOMER_RULE_TFA", - "DEVICE_HOST_CARD_EMULATION", - ] - ] = None - """Reason code for requiring two-factor authentication""" - - -class DailyStatisticVersionExampleActionApproveActionACH(BaseModel): - type: Literal["APPROVE"] - """Approve the ACH transaction""" - - -class DailyStatisticVersionExampleActionReturnAction(BaseModel): - code: Literal[ - "R01", - "R02", - "R03", - "R04", - "R05", - "R06", - "R07", - "R08", - "R09", - "R10", - "R11", - "R12", - "R13", - "R14", - "R15", - "R16", - "R17", - "R18", - "R19", - "R20", - "R21", - "R22", - "R23", - "R24", - "R25", - "R26", - "R27", - "R28", - "R29", - "R30", - "R31", - "R32", - "R33", - "R34", - "R35", - "R36", - "R37", - "R38", - "R39", - "R40", - "R41", - "R42", - "R43", - "R44", - "R45", - "R46", - "R47", - "R50", - "R51", - "R52", - "R53", - "R61", - "R62", - "R67", - "R68", - "R69", - "R70", - "R71", - "R72", - "R73", - "R74", - "R75", - "R76", - "R77", - "R80", - "R81", - "R82", - "R83", - "R84", - "R85", - ] - """NACHA return code to use when returning the transaction. - - Note that the list of available return codes is subject to an allowlist - configured at the program level - """ - - type: Literal["RETURN"] - """Return the ACH transaction""" - - -DailyStatisticVersionExampleAction: TypeAlias = Union[ - DailyStatisticVersionExampleActionDeclineActionAuthorization, - DailyStatisticVersionExampleActionChallengeActionAuthorization, - DailyStatisticVersionExampleActionResultAuthentication3DSAction, - DailyStatisticVersionExampleActionDeclineActionTokenization, - DailyStatisticVersionExampleActionRequireTfaAction, - DailyStatisticVersionExampleActionApproveActionACH, - DailyStatisticVersionExampleActionReturnAction, -] - - -class DailyStatisticVersionExample(BaseModel): - actions: List[DailyStatisticVersionExampleAction] - """The actions taken by this version for this event.""" - - event_token: str - """The event token.""" - - timestamp: datetime.datetime - """The timestamp of the event.""" - - -class DailyStatisticVersion(BaseModel): - action_counts: Dict[str, int] - """ - A mapping of action types to the number of times that action was returned by - this version during the relevant period. Actions are the possible outcomes of a - rule evaluation, such as DECLINE, CHALLENGE, REQUIRE_TFA, etc. In case rule - didn't trigger any action, it's counted under NO_ACTION key. - """ - - examples: List[DailyStatisticVersionExample] - """Example events and their outcomes for this version.""" - - state: Literal["ACTIVE", "SHADOW", "INACTIVE"] - """The evaluation mode of this version during the reported period.""" - - version: int - """The rule version number.""" +__all__ = ["V2RetrieveReportResponse", "DailyStatistic"] class DailyStatistic(BaseModel): - current_version_statistics: Optional[ReportStats] = None - """Detailed statistics for the current version of the rule.""" - date: datetime.date """The date (UTC) for which the statistics are reported.""" - draft_version_statistics: Optional[ReportStats] = None - """Detailed statistics for the draft version of the rule.""" - - versions: List[DailyStatisticVersion] + versions: List[ReportStats] """ Statistics for each version of the rule that was evaluated during the reported day. diff --git a/src/lithic/types/card_authorization_approval_request_webhook_event.py b/src/lithic/types/card_authorization_approval_request_webhook_event.py index e1341b40..489261b9 100644 --- a/src/lithic/types/card_authorization_approval_request_webhook_event.py +++ b/src/lithic/types/card_authorization_approval_request_webhook_event.py @@ -102,23 +102,16 @@ class Avs(BaseModel): class Card(BaseModel): """Card object in ASA""" - token: Optional[str] = None + token: str """Globally unique identifier for the card.""" - hostname: Optional[str] = None - """Hostname of card’s locked merchant (will be empty if not applicable)""" - - last_four: Optional[str] = None + last_four: str """Last four digits of the card number""" - memo: Optional[str] = None - """Customizable name to identify the card. - - We recommend against using this field to store JSON data as it can cause - unexpected behavior. - """ + memo: str + """Customizable name to identify the card""" - spend_limit: Optional[int] = None + spend_limit: int """Amount (in cents) to limit approved authorizations. Purchase requests above the spend limit will be declined (refunds and credits @@ -131,16 +124,16 @@ class Card(BaseModel): authorization). """ - spend_limit_duration: Optional[Literal["ANNUALLY", "FOREVER", "MONTHLY", "TRANSACTION"]] = None + spend_limit_duration: Literal["ANNUALLY", "FOREVER", "MONTHLY", "TRANSACTION"] """ Note that to support recurring monthly payments, which can occur on different day every month, the time window we consider for MONTHLY velocity starts 6 days after the current calendar date one month prior. """ - state: Optional[Literal["CLOSED", "OPEN", "PAUSED", "PENDING_ACTIVATION", "PENDING_FULFILLMENT"]] = None + state: Literal["CLOSED", "OPEN", "PAUSED", "PENDING_ACTIVATION", "PENDING_FULFILLMENT"] - type: Optional[Literal["SINGLE_USE", "MERCHANT_LOCKED", "UNLOCKED", "PHYSICAL", "DIGITAL_WALLET", "VIRTUAL"]] = None + type: Literal["SINGLE_USE", "MERCHANT_LOCKED", "UNLOCKED", "PHYSICAL", "DIGITAL_WALLET", "VIRTUAL"] class Merchant(merchant.Merchant): diff --git a/src/lithic/types/card_bulk_order.py b/src/lithic/types/card_bulk_order.py index c8ad3abc..1ee94d12 100644 --- a/src/lithic/types/card_bulk_order.py +++ b/src/lithic/types/card_bulk_order.py @@ -30,8 +30,12 @@ class CardBulkOrder(BaseModel): shipping_address: object """Shipping address for all cards in this bulk order""" - shipping_method: Literal["BULK_EXPEDITED"] - """Shipping method for all cards in this bulk order""" + shipping_method: Literal["BULK_EXPEDITED", "BULK_PRIORITY", "BULK_2_DAY", "BULK_EXPRESS"] + """Shipping method for all cards in this bulk order. + + BULK_PRIORITY, BULK_2_DAY, and BULK_EXPRESS are only available with Perfect + Plastic Printing + """ status: Literal["OPEN", "LOCKED"] """Status of the bulk order. diff --git a/src/lithic/types/card_bulk_order_create_params.py b/src/lithic/types/card_bulk_order_create_params.py index 641747b6..cfb313a7 100644 --- a/src/lithic/types/card_bulk_order_create_params.py +++ b/src/lithic/types/card_bulk_order_create_params.py @@ -17,5 +17,9 @@ class CardBulkOrderCreateParams(TypedDict, total=False): shipping_address: Required[object] """Shipping address for all cards in this bulk order""" - shipping_method: Required[Literal["BULK_EXPEDITED"]] - """Shipping method for all cards in this bulk order""" + shipping_method: Required[Literal["BULK_EXPEDITED", "BULK_PRIORITY", "BULK_2_DAY", "BULK_EXPRESS"]] + """Shipping method for all cards in this bulk order. + + BULK_PRIORITY, BULK_2_DAY, and BULK_EXPRESS are only available with Perfect + Plastic Printing + """ diff --git a/src/lithic/types/card_convert_physical_params.py b/src/lithic/types/card_convert_physical_params.py index 03911cf0..d2aad1ce 100644 --- a/src/lithic/types/card_convert_physical_params.py +++ b/src/lithic/types/card_convert_physical_params.py @@ -24,9 +24,7 @@ class CardConvertPhysicalParams(TypedDict, total=False): to cards of type `PHYSICAL`. This must be configured with Lithic before use. """ - shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" - ] + shipping_method: Literal["2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING"] """Shipping method for the card. Only applies to cards of type PHYSICAL. Use of options besides `STANDARD` @@ -43,5 +41,6 @@ class CardConvertPhysicalParams(TypedDict, total=False): tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. """ diff --git a/src/lithic/types/card_create_params.py b/src/lithic/types/card_create_params.py index 30e313de..bb1c737f 100644 --- a/src/lithic/types/card_create_params.py +++ b/src/lithic/types/card_create_params.py @@ -165,9 +165,7 @@ class CardCreateParams(TypedDict, total=False): shipping_address: ShippingAddress - shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" - ] + shipping_method: Literal["2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING"] """Shipping method for the card. Only applies to cards of type PHYSICAL. Use of options besides `STANDARD` @@ -184,7 +182,8 @@ class CardCreateParams(TypedDict, total=False): tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. """ spend_limit: int diff --git a/src/lithic/types/card_reissue_params.py b/src/lithic/types/card_reissue_params.py index 828ff228..45de922d 100644 --- a/src/lithic/types/card_reissue_params.py +++ b/src/lithic/types/card_reissue_params.py @@ -24,9 +24,7 @@ class CardReissueParams(TypedDict, total=False): shipping_address: ShippingAddress """If omitted, the previous shipping address will be used.""" - shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" - ] + shipping_method: Literal["2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING"] """Shipping method for the card. Only applies to cards of type PHYSICAL. Use of options besides `STANDARD` @@ -43,5 +41,6 @@ class CardReissueParams(TypedDict, total=False): tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. """ diff --git a/src/lithic/types/card_renew_params.py b/src/lithic/types/card_renew_params.py index e6fcffe2..7f5ac0d8 100644 --- a/src/lithic/types/card_renew_params.py +++ b/src/lithic/types/card_renew_params.py @@ -38,9 +38,7 @@ class CardRenewParams(TypedDict, total=False): to cards of type `PHYSICAL`. This must be configured with Lithic before use. """ - shipping_method: Literal[ - "2_DAY", "BULK_EXPEDITED", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING" - ] + shipping_method: Literal["2_DAY", "BULK", "EXPEDITED", "EXPRESS", "PRIORITY", "STANDARD", "STANDARD_WITH_TRACKING"] """Shipping method for the card. Only applies to cards of type PHYSICAL. Use of options besides `STANDARD` @@ -57,5 +55,6 @@ class CardRenewParams(TypedDict, total=False): tracking - `EXPEDITED` - FedEx or UPS depending on card manufacturer, Standard Overnight or similar international option, with tracking - - `BULK_EXPEDITED` - Bulk shipment with Expedited shipping + - `BULK` - Card will be shipped as part of a bulk fulfillment order. The + shipping method and timeline are inherited from the parent bulk order. """ diff --git a/src/lithic/types/financial_account.py b/src/lithic/types/financial_account.py index f15dfccd..28502aef 100644 --- a/src/lithic/types/financial_account.py +++ b/src/lithic/types/financial_account.py @@ -70,6 +70,7 @@ class FinancialAccount(BaseModel): "COLLECTION", "PROGRAM_BANK_ACCOUNTS_PAYABLE", "EARLY_DIRECT_DEPOSIT_FLOAT", + "PROVISIONAL_CREDIT_ACCOUNT", ] updated: datetime diff --git a/src/lithic/types/financial_accounts/statement.py b/src/lithic/types/financial_accounts/statement.py index 513630fb..afe4a5ce 100644 --- a/src/lithic/types/financial_accounts/statement.py +++ b/src/lithic/types/financial_accounts/statement.py @@ -139,7 +139,7 @@ class Statement(BaseModel): credit_limit: int """This is the maximum credit balance extended by the lender in cents""" - credit_product_token: str + credit_product_token: Optional[str] = None """Globally unique identifier for a credit product""" days_in_billing_cycle: int @@ -185,3 +185,5 @@ class Statement(BaseModel): payoff_details: Optional[PayoffDetails] = None """Details on number and size of payments to pay off balance""" + + statement_totals: Optional[StatementTotals] = None diff --git a/src/lithic/types/payment_create_params.py b/src/lithic/types/payment_create_params.py index c4f01ed9..7a29cc83 100644 --- a/src/lithic/types/payment_create_params.py +++ b/src/lithic/types/payment_create_params.py @@ -43,6 +43,12 @@ class MethodAttributes(TypedDict, total=False): addenda: Optional[str] + override_company_name: Optional[str] + """Value to override the configured company name with. + + Can only be used if allowed to override + """ + class Hold(TypedDict, total=False): """Optional hold to settle when this payment is initiated.""" diff --git a/src/lithic/types/shared/instance_financial_account_type.py b/src/lithic/types/shared/instance_financial_account_type.py index 4cd1bd35..df09d9ff 100644 --- a/src/lithic/types/shared/instance_financial_account_type.py +++ b/src/lithic/types/shared/instance_financial_account_type.py @@ -16,4 +16,5 @@ "COLLECTION", "PROGRAM_BANK_ACCOUNTS_PAYABLE", "EARLY_DIRECT_DEPOSIT_FLOAT", + "PROVISIONAL_CREDIT_ACCOUNT", ] diff --git a/tests/api_resources/test_payments.py b/tests/api_resources/test_payments.py index 864c5031..40083d6f 100644 --- a/tests/api_resources/test_payments.py +++ b/tests/api_resources/test_payments.py @@ -50,6 +50,7 @@ def test_method_create_with_all_params(self, client: Lithic) -> None: "sec_code": "CCD", "ach_hold_period": 0, "addenda": "addenda", + "override_company_name": "override_company_name", }, type="COLLECTION", token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", @@ -473,6 +474,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncLithic) -> "sec_code": "CCD", "ach_hold_period": 0, "addenda": "addenda", + "override_company_name": "override_company_name", }, type="COLLECTION", token="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", diff --git a/tests/test_client.py b/tests/test_client.py index 9cbf4688..b1d87992 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -427,6 +427,30 @@ def test_default_query_option(self) -> None: client.close() + def test_hardcoded_query_params_in_url(self, client: Lithic) -> 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: Lithic) -> None: request = client._build_request( FinalRequestOptions( @@ -1355,6 +1379,30 @@ async def test_default_query_option(self) -> None: await client.close() + async def test_hardcoded_query_params_in_url(self, async_client: AsyncLithic) -> 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: Lithic) -> None: request = client._build_request( FinalRequestOptions( diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 77b1fb75..83bcdade 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", [