diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5bc9245f..084a05eda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/increase-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Rye run: | @@ -44,7 +44,7 @@ jobs: id-token: write runs-on: ${{ github.repository == 'stainless-sdks/increase-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Rye run: | @@ -61,14 +61,18 @@ jobs: run: rye build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/increase-python' + if: |- + github.repository == 'stainless-sdks/increase-python' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v6 + uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball - if: github.repository == 'stainless-sdks/increase-python' + if: |- + github.repository == 'stainless-sdks/increase-python' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} @@ -81,7 +85,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/increase-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Rye run: | diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 10c23f798..6140ad043 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Rye run: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 6ef88fffb..ecb8ea851 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'Increase/increase-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2b0c6a48f..a7230d955 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.423.0" + ".": "0.424.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 6f42a9fee..e4ce02b9a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 227 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase%2Fincrease-0281c1d774b1853b7b09bbce88b8d6e0301179b68d53627c5940edd7d2f8b180.yml -openapi_spec_hash: e22a9d6a4f0f32976d0ac9dd7e6d7dd0 -config_hash: ca52ca9a2968f330339fd50c1a386e05 +configured_endpoints: 234 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase%2Fincrease-dd0c83cac837fbe98857fa997663b0d0469344a7564bd4fe506e6c71d1d6af73.yml +openapi_spec_hash: 2352f37602105b164533038199b21804 +config_hash: b7ec7f54fa76c1f8bde7a548710a1d38 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b5da817e..bd7f54918 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,99 @@ # Changelog +## 0.424.0 (2026-03-08) + +Full Changelog: [v0.423.0...v0.424.0](https://github.com/Increase/increase-python/compare/v0.423.0...v0.424.0) + +### Features + +* **api:** api update ([0f4e499](https://github.com/Increase/increase-python/commit/0f4e4993399535e1fe774239d79a10d3c4525269)) +* **api:** api update ([05625f9](https://github.com/Increase/increase-python/commit/05625f9e01e3ad51054bb28d032aeab3ed0c351a)) +* **api:** api update ([bcd7775](https://github.com/Increase/increase-python/commit/bcd77756ab118d93b48049a12ec616246d198736)) +* **api:** api update ([47de702](https://github.com/Increase/increase-python/commit/47de702e6c114f629300a0d22984500aebd1730c)) +* **api:** api update ([de13518](https://github.com/Increase/increase-python/commit/de13518b9a2b8b8973c683ac7671a36267464442)) +* **api:** api update ([ccf980b](https://github.com/Increase/increase-python/commit/ccf980b91ab731e7a175efa1695c37d844486b90)) +* **api:** api update ([048e16f](https://github.com/Increase/increase-python/commit/048e16fec48ce4eb99bf14cdc4fd86f93fe695ba)) +* **api:** api update ([2355663](https://github.com/Increase/increase-python/commit/2355663b2358359d3724bbf68198fa26130e78db)) +* **api:** api update ([1b951fc](https://github.com/Increase/increase-python/commit/1b951fc6b345d232870ab8d8599797373761c9f7)) +* **api:** api update ([cebada8](https://github.com/Increase/increase-python/commit/cebada88f9721dd06d1191f53ac0bc3a63dd41e8)) +* **api:** api update ([dec4a37](https://github.com/Increase/increase-python/commit/dec4a377c7bf1f08f042a0f7ee222e3e64be87af)) +* **api:** api update ([3b3fc19](https://github.com/Increase/increase-python/commit/3b3fc19c7edf0c98d14dde4ac70fac524805faf4)) +* **api:** api update ([3442155](https://github.com/Increase/increase-python/commit/34421550a4429188ed560a77514e80c11f8eb55c)) +* **api:** api update ([c3e2414](https://github.com/Increase/increase-python/commit/c3e2414e673d4b9a8635a204aa2e0f75a6359417)) +* **api:** api update ([d282186](https://github.com/Increase/increase-python/commit/d2821868e5d5f5c24daa8d4ba8ed980c5fbe9cd5)) +* **api:** api update ([1c50836](https://github.com/Increase/increase-python/commit/1c50836b932c474f2c00fea4d18f706b12dea222)) +* **api:** api update ([346b26f](https://github.com/Increase/increase-python/commit/346b26f20269937e02ccc0f7d3ab9298b02d3403)) +* **api:** api update ([8e1f3d6](https://github.com/Increase/increase-python/commit/8e1f3d600d67efd6524abef843b129d8d76c2063)) +* **api:** api update ([aa940d6](https://github.com/Increase/increase-python/commit/aa940d630904839392db5f8af0a82a252a91be4c)) +* **api:** api update ([434c925](https://github.com/Increase/increase-python/commit/434c925daf1e9e2ae343ceae0f1e9ca6fa787d5e)) +* **api:** api update ([e0cbb65](https://github.com/Increase/increase-python/commit/e0cbb65ebbd673c492cc69c006988555ab424883)) +* **api:** api update ([8bbd0b2](https://github.com/Increase/increase-python/commit/8bbd0b2a6d52b5a8d05eb190257d5713282e7f63)) +* **api:** api update ([2d52596](https://github.com/Increase/increase-python/commit/2d525961950e02b95a678e5d4392fc28b97a2e8e)) +* **api:** api update ([308be9a](https://github.com/Increase/increase-python/commit/308be9a937fa632dc8d2e568b5c43254b7cade7a)) +* **api:** api update ([16bfa54](https://github.com/Increase/increase-python/commit/16bfa54396e9d332977e3355bac08710d04b1896)) +* **api:** api update ([36743f1](https://github.com/Increase/increase-python/commit/36743f18c2dba00923a95d961c112d170d4916ca)) +* **api:** api update ([d3a41a5](https://github.com/Increase/increase-python/commit/d3a41a5e4c4aac2706c3d1e1c4a2557b20050445)) +* **api:** api update ([e6f9590](https://github.com/Increase/increase-python/commit/e6f959019a26f2139760baf04998f4fdcfb97af1)) +* **api:** api update ([999984d](https://github.com/Increase/increase-python/commit/999984df9c58dffaca529a4b9c7842b8247afba4)) +* **api:** api update ([6d88f26](https://github.com/Increase/increase-python/commit/6d88f2644bf8f5bfeed259681ee945497f5aa7a2)) +* **api:** api update ([0ab290b](https://github.com/Increase/increase-python/commit/0ab290b9abfa535ca829da0b2fc479d166b42979)) +* **api:** api update ([cb3ecf4](https://github.com/Increase/increase-python/commit/cb3ecf4693424b7d4cc466fe04f1d24ab5f2d99f)) +* **api:** api update ([af6977d](https://github.com/Increase/increase-python/commit/af6977de206436f49b52aa02d48e25c69c9a96d7)) +* **api:** api update ([55e8402](https://github.com/Increase/increase-python/commit/55e84029d2afbe69808245109b72116fabdd8d4f)) +* **api:** api update ([a37615e](https://github.com/Increase/increase-python/commit/a37615e082764a4256baf6218cab2fd6f25a0fe6)) +* **api:** api update ([9427448](https://github.com/Increase/increase-python/commit/9427448793c7a38cfa9d53c834de382ec5c705a6)) +* **api:** api update ([048542a](https://github.com/Increase/increase-python/commit/048542a172f2d22d0cc956cecf5cb429af1d20d0)) +* **api:** api update ([d8d8381](https://github.com/Increase/increase-python/commit/d8d83819cbb2fbee97dbfb58e930dd6b7604dc26)) +* **api:** api update ([1f971a0](https://github.com/Increase/increase-python/commit/1f971a02f44a982c82e68f3cdde062b0ddfb8aab)) +* **api:** api update ([d40483c](https://github.com/Increase/increase-python/commit/d40483cdf90e0c49b3ce47ab9ed7223459f8c8df)) +* **api:** api update ([352d179](https://github.com/Increase/increase-python/commit/352d179fd2f2c0ae2f825c5e4b7d2bb85346e7ac)) +* **api:** api update ([4f30415](https://github.com/Increase/increase-python/commit/4f304158659361cd6357a9ee400f43c32bcc8d92)) +* **api:** api update ([84fcd3a](https://github.com/Increase/increase-python/commit/84fcd3a5588879a7e3e7e178ce8232898412268d)) +* **api:** api update ([ce854cb](https://github.com/Increase/increase-python/commit/ce854cb66e0c0914646c98ff6acc76826d83633f)) +* **api:** api update ([1197ca9](https://github.com/Increase/increase-python/commit/1197ca9c0353607bf4a648f57f88796820e7d826)) +* **api:** api update ([6cf2279](https://github.com/Increase/increase-python/commit/6cf2279458f94cac5ddc323e2525b4d8984fe5b7)) +* **api:** api update ([1978e1e](https://github.com/Increase/increase-python/commit/1978e1e1739aa81fe7d499c6347ef6214b4476c6)) +* **api:** api update ([a735aaf](https://github.com/Increase/increase-python/commit/a735aafb6cbe7c1c6c7039e3e582581f7d76ca8d)) +* **api:** api update ([5044646](https://github.com/Increase/increase-python/commit/504464608a8cf64b5208bfbf53be7499d3966349)) +* **api:** api update ([136d3c3](https://github.com/Increase/increase-python/commit/136d3c35eaa7ebc12819490c33ee745b8a5c9497)) +* **api:** api update ([ea2cd89](https://github.com/Increase/increase-python/commit/ea2cd892d665853ca8b5b48e024ad14b3c7184f1)) +* **api:** api update ([f5fc2af](https://github.com/Increase/increase-python/commit/f5fc2af3839b55e181959ccb227cb74105db0aa6)) +* **api:** api update ([bfb26e6](https://github.com/Increase/increase-python/commit/bfb26e63a121542fadd90b2c1413fe1a9cef98d0)) +* **api:** api update ([a57c1e0](https://github.com/Increase/increase-python/commit/a57c1e03cd56803ad7ba8284cd9ab56225cd6bce)) +* **api:** api update ([6729890](https://github.com/Increase/increase-python/commit/672989087e07ae1967379b80793b89884f64274f)) +* **api:** api update ([2d48d8d](https://github.com/Increase/increase-python/commit/2d48d8d59f297c50d3d93de80d35564d5fdcf045)) +* **api:** api update ([d419d29](https://github.com/Increase/increase-python/commit/d419d290db4987474a191bd1e1d2a2181e654af5)) +* **api:** api update ([12eb2c7](https://github.com/Increase/increase-python/commit/12eb2c7aec9b45dc79cfc361329610bb000b7746)) +* **api:** api update ([ac98cdf](https://github.com/Increase/increase-python/commit/ac98cdf7eb9115736dcf71afec25f3f3a249eeb7)) +* **api:** api update ([ec99ef5](https://github.com/Increase/increase-python/commit/ec99ef52d27fd2c8a7cacfd9a70ec58351f009c4)) +* **api:** api update ([1a6a043](https://github.com/Increase/increase-python/commit/1a6a0438fa80b72cc1498c1950ad15ee11ed10ee)) +* **api:** api update ([23b9d3c](https://github.com/Increase/increase-python/commit/23b9d3c40d5c6bd37040353baca0107c9af3c991)) +* **api:** api update ([070d55a](https://github.com/Increase/increase-python/commit/070d55af2aa290df6ad3ffa7ae3de6be1e78293e)) +* **api:** api update ([2466c02](https://github.com/Increase/increase-python/commit/2466c02ead61d814dc5fb10a7b4bfc29b1af8fbd)) +* **api:** api update ([8838a73](https://github.com/Increase/increase-python/commit/8838a73025d89de7497da40867d1a77be69b5e55)) +* **api:** api update ([9bb1d10](https://github.com/Increase/increase-python/commit/9bb1d109d8900feb4d62c5130696fb805ac011ef)) +* **api:** api update ([069c147](https://github.com/Increase/increase-python/commit/069c1470c6b072cf20de909113799d2427a972cf)) +* **api:** api update ([981dbcc](https://github.com/Increase/increase-python/commit/981dbcccec3a2a567f335641d0f9b63fd8209168)) +* **client:** add custom JSON encoder for extended type support ([81b193d](https://github.com/Increase/increase-python/commit/81b193d494d84cfd6e53a613888aa64006db864e)) +* **client:** add support for binary request streaming ([15b768f](https://github.com/Increase/increase-python/commit/15b768f8d1fd48b0e356eaf982271805bd84b14c)) + + +### Chores + +* **dependencies:** require standardwebhooks 1.0.1 ([d9cd73a](https://github.com/Increase/increase-python/commit/d9cd73a24319a02201c1f346811e506b35c7b238)) +* format all `api.md` files ([6e81381](https://github.com/Increase/increase-python/commit/6e8138170958c418f5098d0d2edfa6d4504be1ca)) +* **internal:** add request options to SSE classes ([7b0f6ae](https://github.com/Increase/increase-python/commit/7b0f6ae24b1be20b67c0bfa7a338f4cd2a48ab84)) +* **internal:** bump dependencies ([9afb9bc](https://github.com/Increase/increase-python/commit/9afb9bc09a9f54174c5900fa9ad872e667cd1c21)) +* **internal:** codegen related update ([b3c7347](https://github.com/Increase/increase-python/commit/b3c73473e66203ad3f13cfaa1a879906a8e2ecb7)) +* **internal:** codegen related update ([b79b7c6](https://github.com/Increase/increase-python/commit/b79b7c6e67e7aec9f88be120fd71b9b3f3733e9b)) +* **internal:** codegen related update ([60367a0](https://github.com/Increase/increase-python/commit/60367a02110506e6085f56d48150fc47651813bc)) +* **internal:** codegen related update ([e845138](https://github.com/Increase/increase-python/commit/e845138fe4d84aa081d35c6560c165e27a425679)) +* **internal:** fix lint error on Python 3.14 ([db29ffe](https://github.com/Increase/increase-python/commit/db29ffe990d3ec8211873a1fd5b707a6fc87f39c)) +* **internal:** make `test_proxy_environment_variables` more resilient ([e4f191d](https://github.com/Increase/increase-python/commit/e4f191d1ae836381b4f53ba5705ab4e1e7e1948a)) +* **internal:** make `test_proxy_environment_variables` more resilient to env ([a9e3ac5](https://github.com/Increase/increase-python/commit/a9e3ac5340c315d10940df7f12018a00e4534211)) +* **internal:** update `actions/checkout` version ([229bc20](https://github.com/Increase/increase-python/commit/229bc204391e7217777f498c5bb9f3eed187d861)) +* update mock server docs ([97c13ac](https://github.com/Increase/increase-python/commit/97c13acbfa9d91dab213c4dc9961693f24ae2f4f)) + ## 0.423.0 (2026-01-07) Full Changelog: [v0.422.0...v0.423.0](https://github.com/Increase/increase-python/compare/v0.422.0...v0.423.0) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4578ce3ce..cc378bfeb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,8 +88,7 @@ $ pip install ./path-to-wheel-file.whl Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. ```sh -# you will need npm installed -$ npx prism mock path/to/your/openapi.yml +$ ./scripts/mock ``` ```sh diff --git a/api.md b/api.md index f1b050fbc..3859a0c90 100644 --- a/api.md +++ b/api.md @@ -104,7 +104,7 @@ Methods: - client.card_disputes.retrieve(card_dispute_id) -> CardDispute - client.card_disputes.list(\*\*params) -> SyncPage[CardDispute] - client.card_disputes.submit_user_submission(card_dispute_id, \*\*params) -> CardDispute -- client.card_disputes.withdraw(card_dispute_id) -> CardDispute +- client.card_disputes.withdraw(card_dispute_id, \*\*params) -> CardDispute # PhysicalCards @@ -400,6 +400,22 @@ Methods: - client.inbound_fednow_transfers.retrieve(inbound_fednow_transfer_id) -> InboundFednowTransfer - client.inbound_fednow_transfers.list(\*\*params) -> SyncPage[InboundFednowTransfer] +# SwiftTransfers + +Types: + +```python +from increase.types import SwiftTransfer +``` + +Methods: + +- client.swift_transfers.create(\*\*params) -> SwiftTransfer +- client.swift_transfers.retrieve(swift_transfer_id) -> SwiftTransfer +- client.swift_transfers.list(\*\*params) -> SyncPage[SwiftTransfer] +- client.swift_transfers.approve(swift_transfer_id) -> SwiftTransfer +- client.swift_transfers.cancel(swift_transfer_id) -> SwiftTransfer + # CheckDeposits Types: @@ -486,11 +502,8 @@ Methods: - client.entities.list(\*\*params) -> SyncPage[Entity] - client.entities.archive(entity_id) -> Entity - client.entities.archive_beneficial_owner(entity_id, \*\*params) -> Entity -- client.entities.confirm(entity_id, \*\*params) -> Entity - client.entities.create_beneficial_owner(entity_id, \*\*params) -> Entity -- client.entities.update_address(entity_id, \*\*params) -> Entity - client.entities.update_beneficial_owner_address(entity_id, \*\*params) -> Entity -- client.entities.update_industry_code(entity_id, \*\*params) -> Entity # SupplementalDocuments @@ -576,7 +589,7 @@ Methods: Types: ```python -from increase.types import Event +from increase.types import Event, UnwrapWebhookEvent ``` Methods: @@ -865,6 +878,14 @@ Methods: - client.simulations.card_refunds.create(\*\*params) -> Transaction +## CardAuthentications + +Methods: + +- client.simulations.card_authentications.create(\*\*params) -> CardPayment +- client.simulations.card_authentications.challenge_attempts(card_payment_id, \*\*params) -> CardPayment +- client.simulations.card_authentications.challenges(card_payment_id) -> CardPayment + ## CardDisputes Methods: @@ -949,6 +970,7 @@ Methods: Methods: - client.simulations.inbound_check_deposits.create(\*\*params) -> InboundCheckDeposit +- client.simulations.inbound_check_deposits.adjustment(inbound_check_deposit_id, \*\*params) -> InboundCheckDeposit ## RealTimePaymentsTransfers @@ -972,9 +994,10 @@ Methods: Methods: +- client.simulations.check_deposits.adjustment(check_deposit_id, \*\*params) -> CheckDeposit - client.simulations.check_deposits.reject(check_deposit_id) -> CheckDeposit - client.simulations.check*deposits.return*(check_deposit_id) -> CheckDeposit -- client.simulations.check_deposits.submit(check_deposit_id) -> CheckDeposit +- client.simulations.check_deposits.submit(check_deposit_id, \*\*params) -> CheckDeposit ## InboundMailItems diff --git a/pyproject.toml b/pyproject.toml index 4e3009c12..257e70f08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "increase" -version = "0.423.0" +version = "0.424.0" description = "The official Python library for the increase API" dynamic = ["readme"] license = "Apache-2.0" @@ -42,6 +42,7 @@ Repository = "https://github.com/Increase/increase-python" [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] +webhooks = ["standardwebhooks >= 1.0.1, < 2"] [tool.rye] managed = true @@ -69,7 +70,7 @@ format = { chain = [ # run formatting again to fix any inconsistencies when imports are stripped "format:ruff", ]} -"format:docs" = "python scripts/utils/ruffen-docs.py README.md api.md" +"format:docs" = "bash -c 'python scripts/utils/ruffen-docs.py README.md $(find . -type f -name api.md)'" "format:ruff" = "ruff format" "lint" = { chain = [ diff --git a/requirements-dev.lock b/requirements-dev.lock index b89977af4..9a4f79b84 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -12,14 +12,14 @@ -e file:. aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.13.2 +aiohttp==3.13.3 # via httpx-aiohttp # via increase aiosignal==1.4.0 # via aiohttp annotated-types==0.7.0 # via pydantic -anyio==4.12.0 +anyio==4.12.1 # via httpx # via increase argcomplete==3.6.3 @@ -29,15 +29,18 @@ async-timeout==5.0.1 attrs==25.4.0 # via aiohttp # via nox + # via standardwebhooks backports-asyncio-runner==1.2.0 # via pytest-asyncio -certifi==2025.11.12 +certifi==2026.1.4 # via httpcore # via httpx colorlog==6.10.1 # via nox dependency-groups==1.3.1 # via nox +deprecated==1.3.1 + # via standardwebhooks dirty-equals==0.11 distlib==0.4.0 # via virtualenv @@ -61,7 +64,8 @@ httpx==0.28.1 # via httpx-aiohttp # via increase # via respx -httpx-aiohttp==0.1.9 + # via standardwebhooks +httpx-aiohttp==0.1.12 # via increase humanize==4.13.0 # via nox @@ -69,7 +73,7 @@ idna==3.11 # via anyio # via httpx # via yarl -importlib-metadata==8.7.0 +importlib-metadata==8.7.1 iniconfig==2.1.0 # via pytest markdown-it-py==3.0.0 @@ -82,14 +86,14 @@ multidict==6.7.0 mypy==1.17.0 mypy-extensions==1.1.0 # via mypy -nodeenv==1.9.1 +nodeenv==1.10.0 # via pyright nox==2025.11.12 packaging==25.0 # via dependency-groups # via nox # via pytest -pathspec==0.12.1 +pathspec==1.0.3 # via mypy platformdirs==4.4.0 # via virtualenv @@ -112,20 +116,27 @@ pytest==8.4.2 pytest-asyncio==1.2.0 pytest-xdist==3.8.0 python-dateutil==2.9.0.post0 + # via standardwebhooks # via time-machine respx==0.22.0 rich==14.2.0 -ruff==0.14.7 +ruff==0.14.13 six==1.17.0 # via python-dateutil sniffio==1.3.1 # via increase +standardwebhooks==1.0.1 + # via increase time-machine==2.19.0 -tomli==2.3.0 +tomli==2.4.0 # via dependency-groups # via mypy # via nox # via pytest +types-deprecated==1.3.1.20251101 + # via standardwebhooks +types-python-dateutil==2.9.0.20251115 + # via standardwebhooks typing-extensions==4.15.0 # via aiosignal # via anyio @@ -141,8 +152,10 @@ typing-extensions==4.15.0 # via virtualenv typing-inspection==0.4.2 # via pydantic -virtualenv==20.35.4 +virtualenv==20.36.1 # via nox +wrapt==2.0.1 + # via deprecated yarl==1.22.0 # via aiohttp zipp==3.23.0 diff --git a/requirements.lock b/requirements.lock index db5859e44..a730a50a3 100644 --- a/requirements.lock +++ b/requirements.lock @@ -12,23 +12,26 @@ -e file:. aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.13.2 +aiohttp==3.13.3 # via httpx-aiohttp # via increase aiosignal==1.4.0 # via aiohttp annotated-types==0.7.0 # via pydantic -anyio==4.12.0 +anyio==4.12.1 # via httpx # via increase async-timeout==5.0.1 # via aiohttp attrs==25.4.0 # via aiohttp -certifi==2025.11.12 + # via standardwebhooks +certifi==2026.1.4 # via httpcore # via httpx +deprecated==1.3.1 + # via standardwebhooks distro==1.9.0 # via increase exceptiongroup==1.3.1 @@ -43,7 +46,8 @@ httpcore==1.0.9 httpx==0.28.1 # via httpx-aiohttp # via increase -httpx-aiohttp==0.1.9 + # via standardwebhooks +httpx-aiohttp==0.1.12 # via increase idna==3.11 # via anyio @@ -59,8 +63,18 @@ pydantic==2.12.5 # via increase pydantic-core==2.41.5 # via pydantic +python-dateutil==2.9.0.post0 + # via standardwebhooks +six==1.17.0 + # via python-dateutil sniffio==1.3.1 # via increase +standardwebhooks==1.0.1 + # via increase +types-deprecated==1.3.1.20251101 + # via standardwebhooks +types-python-dateutil==2.9.0.20251115 + # via standardwebhooks typing-extensions==4.15.0 # via aiosignal # via anyio @@ -72,5 +86,7 @@ typing-extensions==4.15.0 # via typing-inspection typing-inspection==0.4.2 # via pydantic +wrapt==2.0.1 + # via deprecated yarl==1.22.0 # via aiohttp diff --git a/scripts/mock b/scripts/mock index 0b28f6ea2..bcf3b392b 100755 --- a/scripts/mock +++ b/scripts/mock @@ -21,11 +21,22 @@ echo "==> Starting mock server with URL ${URL}" # Run prism mock on the given spec if [ "$1" == "--daemon" ]; then + # Pre-install the package so the download doesn't eat into the startup timeout + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & - # Wait for server to come online + # Wait for server to come online (max 30s) echo -n "Waiting for server" + attempts=0 while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + attempts=$((attempts + 1)) + if [ "$attempts" -ge 300 ]; then + echo + echo "Timed out waiting for Prism server to start" + cat .prism.log + exit 1 + fi echo -n "." sleep 0.1 done diff --git a/src/increase/__init__.py b/src/increase/__init__.py index 740cd3665..55ed1eb5d 100644 --- a/src/increase/__init__.py +++ b/src/increase/__init__.py @@ -44,6 +44,7 @@ InvalidParametersError, EnvironmentMismatchError, UnprocessableEntityError, + APIWebhookValidationError, APIResponseValidationError, InsufficientPermissionsError, IdempotencyKeyAlreadyUsedError, @@ -69,6 +70,7 @@ "APITimeoutError", "APIConnectionError", "APIResponseValidationError", + "APIWebhookValidationError", "BadRequestError", "AuthenticationError", "PermissionDeniedError", diff --git a/src/increase/_base_client.py b/src/increase/_base_client.py index ac8ef78c1..3b68bfe23 100644 --- a/src/increase/_base_client.py +++ b/src/increase/_base_client.py @@ -9,6 +9,7 @@ import inspect import logging import platform +import warnings import email.utils from types import TracebackType from random import random @@ -51,9 +52,11 @@ ResponseT, AnyMapping, PostParser, + BinaryTypes, RequestFiles, HttpxSendArgs, RequestOptions, + AsyncBinaryTypes, HttpxRequestFiles, ModelBuilderProtocol, not_given, @@ -83,6 +86,7 @@ APIConnectionError, APIResponseValidationError, ) +from ._utils._json import openapi_dumps log: logging.Logger = logging.getLogger(__name__) @@ -477,8 +481,19 @@ def _build_request( retries_taken: int = 0, ) -> httpx.Request: if log.isEnabledFor(logging.DEBUG): - log.debug("Request options: %s", model_dump(options, exclude_unset=True)) - + log.debug( + "Request options: %s", + model_dump( + options, + exclude_unset=True, + # Pydantic v1 can't dump every type we support in content, so we exclude it for now. + exclude={ + "content", + } + if PYDANTIC_V1 + else {}, + ), + ) kwargs: dict[str, Any] = {} json_data = options.json_data @@ -532,10 +547,18 @@ def _build_request( is_body_allowed = options.method.lower() != "get" if is_body_allowed: - if isinstance(json_data, bytes): + if options.content is not None and json_data is not None: + raise TypeError("Passing both `content` and `json_data` is not supported") + if options.content is not None and files is not None: + raise TypeError("Passing both `content` and `files` is not supported") + if options.content is not None: + kwargs["content"] = options.content + elif isinstance(json_data, bytes): kwargs["content"] = json_data - else: - kwargs["json"] = json_data if is_given(json_data) else None + elif not files: + # Don't set content when JSON is sent as multipart/form-data, + # since httpx's content param overrides other body arguments + kwargs["content"] = openapi_dumps(json_data) if is_given(json_data) and json_data is not None else None kwargs["files"] = files else: headers.pop("Content-Type", None) @@ -1019,6 +1042,7 @@ def request( response.reason_phrase, response.headers, ) + log.debug("idempotent_replayed: %s", response.headers.get("Idempotent-Replayed")) try: response.raise_for_status() @@ -1194,6 +1218,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[False] = False, @@ -1206,6 +1231,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[True], @@ -1219,6 +1245,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: bool, @@ -1231,13 +1258,25 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: bool = False, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="post", url=path, json_data=body, files=to_httpx_files(files), **options + method="post", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) @@ -1247,11 +1286,23 @@ def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="patch", url=path, json_data=body, files=to_httpx_files(files), **options + method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return self.request(cast_to, opts) @@ -1261,11 +1312,23 @@ def put( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="put", url=path, json_data=body, files=to_httpx_files(files), **options + method="put", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return self.request(cast_to, opts) @@ -1275,9 +1338,19 @@ def delete( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options) + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) + opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options) return self.request(cast_to, opts) def get_api_list( @@ -1554,6 +1627,7 @@ async def request( response.reason_phrase, response.headers, ) + log.debug("idempotent_replayed: %s", response.headers.get("Idempotent-Replayed")) try: response.raise_for_status() @@ -1717,6 +1791,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[False] = False, @@ -1729,6 +1804,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[True], @@ -1742,6 +1818,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: bool, @@ -1754,13 +1831,25 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: bool = False, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="post", url=path, json_data=body, files=await async_to_httpx_files(files), **options + method="post", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) @@ -1770,11 +1859,28 @@ async def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="patch", url=path, json_data=body, files=await async_to_httpx_files(files), **options + method="patch", + url=path, + json_data=body, + content=content, + files=await async_to_httpx_files(files), + **options, ) return await self.request(cast_to, opts) @@ -1784,11 +1890,23 @@ async def put( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="put", url=path, json_data=body, files=await async_to_httpx_files(files), **options + method="put", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts) @@ -1798,9 +1916,19 @@ async def delete( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options) + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) + opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options) return await self.request(cast_to, opts) def get_api_list( diff --git a/src/increase/_client.py b/src/increase/_client.py index a4bc4519b..fd7161b9f 100644 --- a/src/increase/_client.py +++ b/src/increase/_client.py @@ -35,415 +35,118 @@ ) if TYPE_CHECKING: - from .resources.cards import ( - CardsResource, - AsyncCardsResource, - CardsResourceWithRawResponse, - AsyncCardsResourceWithRawResponse, - CardsResourceWithStreamingResponse, - AsyncCardsResourceWithStreamingResponse, - ) - from .resources.files import ( - FilesResource, - AsyncFilesResource, - FilesResourceWithRawResponse, - AsyncFilesResourceWithRawResponse, - FilesResourceWithStreamingResponse, - AsyncFilesResourceWithStreamingResponse, - ) - from .resources.events import ( - EventsResource, - AsyncEventsResource, - EventsResourceWithRawResponse, - AsyncEventsResourceWithRawResponse, - EventsResourceWithStreamingResponse, - AsyncEventsResourceWithStreamingResponse, - ) - from .resources.groups import ( - GroupsResource, - AsyncGroupsResource, - GroupsResourceWithRawResponse, - AsyncGroupsResourceWithRawResponse, - GroupsResourceWithStreamingResponse, - AsyncGroupsResourceWithStreamingResponse, - ) - from .resources.exports import ( - ExportsResource, - AsyncExportsResource, - ExportsResourceWithRawResponse, - AsyncExportsResourceWithRawResponse, - ExportsResourceWithStreamingResponse, - AsyncExportsResourceWithStreamingResponse, - ) - from .resources.accounts import ( - AccountsResource, - AsyncAccountsResource, - AccountsResourceWithRawResponse, - AsyncAccountsResourceWithRawResponse, - AccountsResourceWithStreamingResponse, - AsyncAccountsResourceWithStreamingResponse, - ) - from .resources.entities import ( - EntitiesResource, - AsyncEntitiesResource, - EntitiesResourceWithRawResponse, - AsyncEntitiesResourceWithRawResponse, - EntitiesResourceWithStreamingResponse, - AsyncEntitiesResourceWithStreamingResponse, - ) - from .resources.programs import ( - ProgramsResource, - AsyncProgramsResource, - ProgramsResourceWithRawResponse, - AsyncProgramsResourceWithRawResponse, - ProgramsResourceWithStreamingResponse, - AsyncProgramsResourceWithStreamingResponse, + from .resources import ( + cards, + files, + events, + groups, + exports, + accounts, + entities, + programs, + lockboxes, + file_links, + card_tokens, + simulations, + oauth_tokens, + transactions, + ach_transfers, + card_disputes, + card_payments, + check_deposits, + physical_cards, + wire_transfers, + account_numbers, + check_transfers, + routing_numbers, + swift_transfers, + card_validations, + fednow_transfers, + intrafi_balances, + account_transfers, + external_accounts, + oauth_connections, + account_statements, + inbound_mail_items, + intrafi_exclusions, + oauth_applications, + bookkeeping_entries, + card_push_transfers, + event_subscriptions, + real_time_decisions, + ach_prenotifications, + bookkeeping_accounts, + pending_transactions, + declined_transactions, + digital_card_profiles, + digital_wallet_tokens, + inbound_ach_transfers, + bookkeeping_entry_sets, + inbound_check_deposits, + inbound_wire_transfers, + physical_card_profiles, + supplemental_documents, + wire_drawdown_requests, + inbound_fednow_transfers, + card_purchase_supplements, + intrafi_account_enrollments, + real_time_payments_transfers, + inbound_wire_drawdown_requests, + inbound_real_time_payments_transfers, ) + from .resources.cards import CardsResource, AsyncCardsResource + from .resources.files import FilesResource, AsyncFilesResource + from .resources.events import EventsResource, AsyncEventsResource + from .resources.groups import GroupsResource, AsyncGroupsResource + from .resources.exports import ExportsResource, AsyncExportsResource + from .resources.accounts import AccountsResource, AsyncAccountsResource + from .resources.entities import EntitiesResource, AsyncEntitiesResource + from .resources.programs import ProgramsResource, AsyncProgramsResource from .resources.webhooks import Webhooks, AsyncWebhooks - from .resources.lockboxes import ( - LockboxesResource, - AsyncLockboxesResource, - LockboxesResourceWithRawResponse, - AsyncLockboxesResourceWithRawResponse, - LockboxesResourceWithStreamingResponse, - AsyncLockboxesResourceWithStreamingResponse, - ) - from .resources.file_links import ( - FileLinksResource, - AsyncFileLinksResource, - FileLinksResourceWithRawResponse, - AsyncFileLinksResourceWithRawResponse, - FileLinksResourceWithStreamingResponse, - AsyncFileLinksResourceWithStreamingResponse, - ) - from .resources.card_tokens import ( - CardTokensResource, - AsyncCardTokensResource, - CardTokensResourceWithRawResponse, - AsyncCardTokensResourceWithRawResponse, - CardTokensResourceWithStreamingResponse, - AsyncCardTokensResourceWithStreamingResponse, - ) - from .resources.oauth_tokens import ( - OAuthTokensResource, - AsyncOAuthTokensResource, - OAuthTokensResourceWithRawResponse, - AsyncOAuthTokensResourceWithRawResponse, - OAuthTokensResourceWithStreamingResponse, - AsyncOAuthTokensResourceWithStreamingResponse, - ) - from .resources.transactions import ( - TransactionsResource, - AsyncTransactionsResource, - TransactionsResourceWithRawResponse, - AsyncTransactionsResourceWithRawResponse, - TransactionsResourceWithStreamingResponse, - AsyncTransactionsResourceWithStreamingResponse, - ) - from .resources.ach_transfers import ( - ACHTransfersResource, - AsyncACHTransfersResource, - ACHTransfersResourceWithRawResponse, - AsyncACHTransfersResourceWithRawResponse, - ACHTransfersResourceWithStreamingResponse, - AsyncACHTransfersResourceWithStreamingResponse, - ) - from .resources.card_disputes import ( - CardDisputesResource, - AsyncCardDisputesResource, - CardDisputesResourceWithRawResponse, - AsyncCardDisputesResourceWithRawResponse, - CardDisputesResourceWithStreamingResponse, - AsyncCardDisputesResourceWithStreamingResponse, - ) - from .resources.card_payments import ( - CardPaymentsResource, - AsyncCardPaymentsResource, - CardPaymentsResourceWithRawResponse, - AsyncCardPaymentsResourceWithRawResponse, - CardPaymentsResourceWithStreamingResponse, - AsyncCardPaymentsResourceWithStreamingResponse, - ) - from .resources.check_deposits import ( - CheckDepositsResource, - AsyncCheckDepositsResource, - CheckDepositsResourceWithRawResponse, - AsyncCheckDepositsResourceWithRawResponse, - CheckDepositsResourceWithStreamingResponse, - AsyncCheckDepositsResourceWithStreamingResponse, - ) - from .resources.physical_cards import ( - PhysicalCardsResource, - AsyncPhysicalCardsResource, - PhysicalCardsResourceWithRawResponse, - AsyncPhysicalCardsResourceWithRawResponse, - PhysicalCardsResourceWithStreamingResponse, - AsyncPhysicalCardsResourceWithStreamingResponse, - ) - from .resources.wire_transfers import ( - WireTransfersResource, - AsyncWireTransfersResource, - WireTransfersResourceWithRawResponse, - AsyncWireTransfersResourceWithRawResponse, - WireTransfersResourceWithStreamingResponse, - AsyncWireTransfersResourceWithStreamingResponse, - ) - from .resources.account_numbers import ( - AccountNumbersResource, - AsyncAccountNumbersResource, - AccountNumbersResourceWithRawResponse, - AsyncAccountNumbersResourceWithRawResponse, - AccountNumbersResourceWithStreamingResponse, - AsyncAccountNumbersResourceWithStreamingResponse, - ) - from .resources.check_transfers import ( - CheckTransfersResource, - AsyncCheckTransfersResource, - CheckTransfersResourceWithRawResponse, - AsyncCheckTransfersResourceWithRawResponse, - CheckTransfersResourceWithStreamingResponse, - AsyncCheckTransfersResourceWithStreamingResponse, - ) - from .resources.routing_numbers import ( - RoutingNumbersResource, - AsyncRoutingNumbersResource, - RoutingNumbersResourceWithRawResponse, - AsyncRoutingNumbersResourceWithRawResponse, - RoutingNumbersResourceWithStreamingResponse, - AsyncRoutingNumbersResourceWithStreamingResponse, - ) - from .resources.card_validations import ( - CardValidationsResource, - AsyncCardValidationsResource, - CardValidationsResourceWithRawResponse, - AsyncCardValidationsResourceWithRawResponse, - CardValidationsResourceWithStreamingResponse, - AsyncCardValidationsResourceWithStreamingResponse, - ) - from .resources.fednow_transfers import ( - FednowTransfersResource, - AsyncFednowTransfersResource, - FednowTransfersResourceWithRawResponse, - AsyncFednowTransfersResourceWithRawResponse, - FednowTransfersResourceWithStreamingResponse, - AsyncFednowTransfersResourceWithStreamingResponse, - ) - from .resources.intrafi_balances import ( - IntrafiBalancesResource, - AsyncIntrafiBalancesResource, - IntrafiBalancesResourceWithRawResponse, - AsyncIntrafiBalancesResourceWithRawResponse, - IntrafiBalancesResourceWithStreamingResponse, - AsyncIntrafiBalancesResourceWithStreamingResponse, - ) - from .resources.account_transfers import ( - AccountTransfersResource, - AsyncAccountTransfersResource, - AccountTransfersResourceWithRawResponse, - AsyncAccountTransfersResourceWithRawResponse, - AccountTransfersResourceWithStreamingResponse, - AsyncAccountTransfersResourceWithStreamingResponse, - ) - from .resources.external_accounts import ( - ExternalAccountsResource, - AsyncExternalAccountsResource, - ExternalAccountsResourceWithRawResponse, - AsyncExternalAccountsResourceWithRawResponse, - ExternalAccountsResourceWithStreamingResponse, - AsyncExternalAccountsResourceWithStreamingResponse, - ) - from .resources.oauth_connections import ( - OAuthConnectionsResource, - AsyncOAuthConnectionsResource, - OAuthConnectionsResourceWithRawResponse, - AsyncOAuthConnectionsResourceWithRawResponse, - OAuthConnectionsResourceWithStreamingResponse, - AsyncOAuthConnectionsResourceWithStreamingResponse, - ) - from .resources.account_statements import ( - AccountStatementsResource, - AsyncAccountStatementsResource, - AccountStatementsResourceWithRawResponse, - AsyncAccountStatementsResourceWithRawResponse, - AccountStatementsResourceWithStreamingResponse, - AsyncAccountStatementsResourceWithStreamingResponse, - ) - from .resources.inbound_mail_items import ( - InboundMailItemsResource, - AsyncInboundMailItemsResource, - InboundMailItemsResourceWithRawResponse, - AsyncInboundMailItemsResourceWithRawResponse, - InboundMailItemsResourceWithStreamingResponse, - AsyncInboundMailItemsResourceWithStreamingResponse, - ) - from .resources.intrafi_exclusions import ( - IntrafiExclusionsResource, - AsyncIntrafiExclusionsResource, - IntrafiExclusionsResourceWithRawResponse, - AsyncIntrafiExclusionsResourceWithRawResponse, - IntrafiExclusionsResourceWithStreamingResponse, - AsyncIntrafiExclusionsResourceWithStreamingResponse, - ) - from .resources.oauth_applications import ( - OAuthApplicationsResource, - AsyncOAuthApplicationsResource, - OAuthApplicationsResourceWithRawResponse, - AsyncOAuthApplicationsResourceWithRawResponse, - OAuthApplicationsResourceWithStreamingResponse, - AsyncOAuthApplicationsResourceWithStreamingResponse, - ) - from .resources.bookkeeping_entries import ( - BookkeepingEntriesResource, - AsyncBookkeepingEntriesResource, - BookkeepingEntriesResourceWithRawResponse, - AsyncBookkeepingEntriesResourceWithRawResponse, - BookkeepingEntriesResourceWithStreamingResponse, - AsyncBookkeepingEntriesResourceWithStreamingResponse, - ) - from .resources.card_push_transfers import ( - CardPushTransfersResource, - AsyncCardPushTransfersResource, - CardPushTransfersResourceWithRawResponse, - AsyncCardPushTransfersResourceWithRawResponse, - CardPushTransfersResourceWithStreamingResponse, - AsyncCardPushTransfersResourceWithStreamingResponse, - ) - from .resources.event_subscriptions import ( - EventSubscriptionsResource, - AsyncEventSubscriptionsResource, - EventSubscriptionsResourceWithRawResponse, - AsyncEventSubscriptionsResourceWithRawResponse, - EventSubscriptionsResourceWithStreamingResponse, - AsyncEventSubscriptionsResourceWithStreamingResponse, - ) - from .resources.real_time_decisions import ( - RealTimeDecisionsResource, - AsyncRealTimeDecisionsResource, - RealTimeDecisionsResourceWithRawResponse, - AsyncRealTimeDecisionsResourceWithRawResponse, - RealTimeDecisionsResourceWithStreamingResponse, - AsyncRealTimeDecisionsResourceWithStreamingResponse, - ) - from .resources.ach_prenotifications import ( - ACHPrenotificationsResource, - AsyncACHPrenotificationsResource, - ACHPrenotificationsResourceWithRawResponse, - AsyncACHPrenotificationsResourceWithRawResponse, - ACHPrenotificationsResourceWithStreamingResponse, - AsyncACHPrenotificationsResourceWithStreamingResponse, - ) - from .resources.bookkeeping_accounts import ( - BookkeepingAccountsResource, - AsyncBookkeepingAccountsResource, - BookkeepingAccountsResourceWithRawResponse, - AsyncBookkeepingAccountsResourceWithRawResponse, - BookkeepingAccountsResourceWithStreamingResponse, - AsyncBookkeepingAccountsResourceWithStreamingResponse, - ) - from .resources.pending_transactions import ( - PendingTransactionsResource, - AsyncPendingTransactionsResource, - PendingTransactionsResourceWithRawResponse, - AsyncPendingTransactionsResourceWithRawResponse, - PendingTransactionsResourceWithStreamingResponse, - AsyncPendingTransactionsResourceWithStreamingResponse, - ) - from .resources.declined_transactions import ( - DeclinedTransactionsResource, - AsyncDeclinedTransactionsResource, - DeclinedTransactionsResourceWithRawResponse, - AsyncDeclinedTransactionsResourceWithRawResponse, - DeclinedTransactionsResourceWithStreamingResponse, - AsyncDeclinedTransactionsResourceWithStreamingResponse, - ) - from .resources.digital_card_profiles import ( - DigitalCardProfilesResource, - AsyncDigitalCardProfilesResource, - DigitalCardProfilesResourceWithRawResponse, - AsyncDigitalCardProfilesResourceWithRawResponse, - DigitalCardProfilesResourceWithStreamingResponse, - AsyncDigitalCardProfilesResourceWithStreamingResponse, - ) - from .resources.digital_wallet_tokens import ( - DigitalWalletTokensResource, - AsyncDigitalWalletTokensResource, - DigitalWalletTokensResourceWithRawResponse, - AsyncDigitalWalletTokensResourceWithRawResponse, - DigitalWalletTokensResourceWithStreamingResponse, - AsyncDigitalWalletTokensResourceWithStreamingResponse, - ) - from .resources.inbound_ach_transfers import ( - InboundACHTransfersResource, - AsyncInboundACHTransfersResource, - InboundACHTransfersResourceWithRawResponse, - AsyncInboundACHTransfersResourceWithRawResponse, - InboundACHTransfersResourceWithStreamingResponse, - AsyncInboundACHTransfersResourceWithStreamingResponse, - ) - from .resources.bookkeeping_entry_sets import ( - BookkeepingEntrySetsResource, - AsyncBookkeepingEntrySetsResource, - BookkeepingEntrySetsResourceWithRawResponse, - AsyncBookkeepingEntrySetsResourceWithRawResponse, - BookkeepingEntrySetsResourceWithStreamingResponse, - AsyncBookkeepingEntrySetsResourceWithStreamingResponse, - ) - from .resources.inbound_check_deposits import ( - InboundCheckDepositsResource, - AsyncInboundCheckDepositsResource, - InboundCheckDepositsResourceWithRawResponse, - AsyncInboundCheckDepositsResourceWithRawResponse, - InboundCheckDepositsResourceWithStreamingResponse, - AsyncInboundCheckDepositsResourceWithStreamingResponse, - ) - from .resources.inbound_wire_transfers import ( - InboundWireTransfersResource, - AsyncInboundWireTransfersResource, - InboundWireTransfersResourceWithRawResponse, - AsyncInboundWireTransfersResourceWithRawResponse, - InboundWireTransfersResourceWithStreamingResponse, - AsyncInboundWireTransfersResourceWithStreamingResponse, - ) - from .resources.physical_card_profiles import ( - PhysicalCardProfilesResource, - AsyncPhysicalCardProfilesResource, - PhysicalCardProfilesResourceWithRawResponse, - AsyncPhysicalCardProfilesResourceWithRawResponse, - PhysicalCardProfilesResourceWithStreamingResponse, - AsyncPhysicalCardProfilesResourceWithStreamingResponse, - ) - from .resources.supplemental_documents import ( - SupplementalDocumentsResource, - AsyncSupplementalDocumentsResource, - SupplementalDocumentsResourceWithRawResponse, - AsyncSupplementalDocumentsResourceWithRawResponse, - SupplementalDocumentsResourceWithStreamingResponse, - AsyncSupplementalDocumentsResourceWithStreamingResponse, - ) - from .resources.wire_drawdown_requests import ( - WireDrawdownRequestsResource, - AsyncWireDrawdownRequestsResource, - WireDrawdownRequestsResourceWithRawResponse, - AsyncWireDrawdownRequestsResourceWithRawResponse, - WireDrawdownRequestsResourceWithStreamingResponse, - AsyncWireDrawdownRequestsResourceWithStreamingResponse, - ) - from .resources.simulations.simulations import ( - SimulationsResource, - AsyncSimulationsResource, - SimulationsResourceWithRawResponse, - AsyncSimulationsResourceWithRawResponse, - SimulationsResourceWithStreamingResponse, - AsyncSimulationsResourceWithStreamingResponse, - ) - from .resources.inbound_fednow_transfers import ( - InboundFednowTransfersResource, - AsyncInboundFednowTransfersResource, - InboundFednowTransfersResourceWithRawResponse, - AsyncInboundFednowTransfersResourceWithRawResponse, - InboundFednowTransfersResourceWithStreamingResponse, - AsyncInboundFednowTransfersResourceWithStreamingResponse, - ) + from .resources.lockboxes import LockboxesResource, AsyncLockboxesResource + from .resources.file_links import FileLinksResource, AsyncFileLinksResource + from .resources.card_tokens import CardTokensResource, AsyncCardTokensResource + from .resources.oauth_tokens import OAuthTokensResource, AsyncOAuthTokensResource + from .resources.transactions import TransactionsResource, AsyncTransactionsResource + from .resources.ach_transfers import ACHTransfersResource, AsyncACHTransfersResource + from .resources.card_disputes import CardDisputesResource, AsyncCardDisputesResource + from .resources.card_payments import CardPaymentsResource, AsyncCardPaymentsResource + from .resources.check_deposits import CheckDepositsResource, AsyncCheckDepositsResource + from .resources.physical_cards import PhysicalCardsResource, AsyncPhysicalCardsResource + from .resources.wire_transfers import WireTransfersResource, AsyncWireTransfersResource + from .resources.account_numbers import AccountNumbersResource, AsyncAccountNumbersResource + from .resources.check_transfers import CheckTransfersResource, AsyncCheckTransfersResource + from .resources.routing_numbers import RoutingNumbersResource, AsyncRoutingNumbersResource + from .resources.swift_transfers import SwiftTransfersResource, AsyncSwiftTransfersResource + from .resources.card_validations import CardValidationsResource, AsyncCardValidationsResource + from .resources.fednow_transfers import FednowTransfersResource, AsyncFednowTransfersResource + from .resources.intrafi_balances import IntrafiBalancesResource, AsyncIntrafiBalancesResource + from .resources.account_transfers import AccountTransfersResource, AsyncAccountTransfersResource + from .resources.external_accounts import ExternalAccountsResource, AsyncExternalAccountsResource + from .resources.oauth_connections import OAuthConnectionsResource, AsyncOAuthConnectionsResource + from .resources.account_statements import AccountStatementsResource, AsyncAccountStatementsResource + from .resources.inbound_mail_items import InboundMailItemsResource, AsyncInboundMailItemsResource + from .resources.intrafi_exclusions import IntrafiExclusionsResource, AsyncIntrafiExclusionsResource + from .resources.oauth_applications import OAuthApplicationsResource, AsyncOAuthApplicationsResource + from .resources.bookkeeping_entries import BookkeepingEntriesResource, AsyncBookkeepingEntriesResource + from .resources.card_push_transfers import CardPushTransfersResource, AsyncCardPushTransfersResource + from .resources.event_subscriptions import EventSubscriptionsResource, AsyncEventSubscriptionsResource + from .resources.real_time_decisions import RealTimeDecisionsResource, AsyncRealTimeDecisionsResource + from .resources.ach_prenotifications import ACHPrenotificationsResource, AsyncACHPrenotificationsResource + from .resources.bookkeeping_accounts import BookkeepingAccountsResource, AsyncBookkeepingAccountsResource + from .resources.pending_transactions import PendingTransactionsResource, AsyncPendingTransactionsResource + from .resources.declined_transactions import DeclinedTransactionsResource, AsyncDeclinedTransactionsResource + from .resources.digital_card_profiles import DigitalCardProfilesResource, AsyncDigitalCardProfilesResource + from .resources.digital_wallet_tokens import DigitalWalletTokensResource, AsyncDigitalWalletTokensResource + from .resources.inbound_ach_transfers import InboundACHTransfersResource, AsyncInboundACHTransfersResource + from .resources.bookkeeping_entry_sets import BookkeepingEntrySetsResource, AsyncBookkeepingEntrySetsResource + from .resources.inbound_check_deposits import InboundCheckDepositsResource, AsyncInboundCheckDepositsResource + from .resources.inbound_wire_transfers import InboundWireTransfersResource, AsyncInboundWireTransfersResource + from .resources.physical_card_profiles import PhysicalCardProfilesResource, AsyncPhysicalCardProfilesResource + from .resources.supplemental_documents import SupplementalDocumentsResource, AsyncSupplementalDocumentsResource + from .resources.wire_drawdown_requests import WireDrawdownRequestsResource, AsyncWireDrawdownRequestsResource + from .resources.simulations.simulations import SimulationsResource, AsyncSimulationsResource + from .resources.inbound_fednow_transfers import InboundFednowTransfersResource, AsyncInboundFednowTransfersResource from .resources.card_purchase_supplements import ( CardPurchaseSupplementsResource, AsyncCardPurchaseSupplementsResource, @@ -754,6 +457,12 @@ def inbound_fednow_transfers(self) -> InboundFednowTransfersResource: return InboundFednowTransfersResource(self) + @cached_property + def swift_transfers(self) -> SwiftTransfersResource: + from .resources.swift_transfers import SwiftTransfersResource + + return SwiftTransfersResource(self) + @cached_property def check_deposits(self) -> CheckDepositsResource: from .resources.check_deposits import CheckDepositsResource @@ -1347,6 +1056,12 @@ def inbound_fednow_transfers(self) -> AsyncInboundFednowTransfersResource: return AsyncInboundFednowTransfersResource(self) + @cached_property + def swift_transfers(self) -> AsyncSwiftTransfersResource: + from .resources.swift_transfers import AsyncSwiftTransfersResource + + return AsyncSwiftTransfersResource(self) + @cached_property def check_deposits(self) -> AsyncCheckDepositsResource: from .resources.check_deposits import AsyncCheckDepositsResource @@ -1867,6 +1582,12 @@ def inbound_fednow_transfers(self) -> InboundFednowTransfersResourceWithRawRespo return InboundFednowTransfersResourceWithRawResponse(self._client.inbound_fednow_transfers) + @cached_property + def swift_transfers(self) -> swift_transfers.SwiftTransfersResourceWithRawResponse: + from .resources.swift_transfers import SwiftTransfersResourceWithRawResponse + + return SwiftTransfersResourceWithRawResponse(self._client.swift_transfers) + @cached_property def check_deposits(self) -> CheckDepositsResourceWithRawResponse: from .resources.check_deposits import CheckDepositsResourceWithRawResponse @@ -2224,6 +1945,12 @@ def inbound_fednow_transfers(self) -> AsyncInboundFednowTransfersResourceWithRaw return AsyncInboundFednowTransfersResourceWithRawResponse(self._client.inbound_fednow_transfers) + @cached_property + def swift_transfers(self) -> swift_transfers.AsyncSwiftTransfersResourceWithRawResponse: + from .resources.swift_transfers import AsyncSwiftTransfersResourceWithRawResponse + + return AsyncSwiftTransfersResourceWithRawResponse(self._client.swift_transfers) + @cached_property def check_deposits(self) -> AsyncCheckDepositsResourceWithRawResponse: from .resources.check_deposits import AsyncCheckDepositsResourceWithRawResponse @@ -2581,6 +2308,12 @@ def inbound_fednow_transfers(self) -> InboundFednowTransfersResourceWithStreamin return InboundFednowTransfersResourceWithStreamingResponse(self._client.inbound_fednow_transfers) + @cached_property + def swift_transfers(self) -> swift_transfers.SwiftTransfersResourceWithStreamingResponse: + from .resources.swift_transfers import SwiftTransfersResourceWithStreamingResponse + + return SwiftTransfersResourceWithStreamingResponse(self._client.swift_transfers) + @cached_property def check_deposits(self) -> CheckDepositsResourceWithStreamingResponse: from .resources.check_deposits import CheckDepositsResourceWithStreamingResponse @@ -2944,6 +2677,12 @@ def inbound_fednow_transfers( return AsyncInboundFednowTransfersResourceWithStreamingResponse(self._client.inbound_fednow_transfers) + @cached_property + def swift_transfers(self) -> swift_transfers.AsyncSwiftTransfersResourceWithStreamingResponse: + from .resources.swift_transfers import AsyncSwiftTransfersResourceWithStreamingResponse + + return AsyncSwiftTransfersResourceWithStreamingResponse(self._client.swift_transfers) + @cached_property def check_deposits(self) -> AsyncCheckDepositsResourceWithStreamingResponse: from .resources.check_deposits import AsyncCheckDepositsResourceWithStreamingResponse diff --git a/src/increase/_compat.py b/src/increase/_compat.py index bdef67f04..786ff42ad 100644 --- a/src/increase/_compat.py +++ b/src/increase/_compat.py @@ -139,6 +139,7 @@ def model_dump( exclude_defaults: bool = False, warnings: bool = True, mode: Literal["json", "python"] = "python", + by_alias: bool | None = None, ) -> dict[str, Any]: if (not PYDANTIC_V1) or hasattr(model, "model_dump"): return model.model_dump( @@ -148,13 +149,12 @@ def model_dump( exclude_defaults=exclude_defaults, # warnings are not supported in Pydantic v1 warnings=True if PYDANTIC_V1 else warnings, + by_alias=by_alias, ) return cast( "dict[str, Any]", model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast] - exclude=exclude, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, + exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias) ), ) diff --git a/src/increase/_exceptions.py b/src/increase/_exceptions.py index a330649bd..66d395d78 100644 --- a/src/increase/_exceptions.py +++ b/src/increase/_exceptions.py @@ -69,16 +69,22 @@ def __init__(self, response: httpx.Response, body: object | None, *, message: st self.status_code = response.status_code +class APIWebhookValidationError(APIError): + pass + + class APIStatusError(APIError): """Raised when an API response has a status code of 4xx or 5xx.""" response: httpx.Response status_code: int + idempotent_replayed: str | None def __init__(self, message: str, *, response: httpx.Response, body: object | None) -> None: super().__init__(message, response.request, body=body) self.response = response self.status_code = response.status_code + self.idempotent_replayed = response.headers.get("Idempotent-Replayed") class APIConnectionError(APIError): diff --git a/src/increase/_models.py b/src/increase/_models.py index ca9500b2a..29070e055 100644 --- a/src/increase/_models.py +++ b/src/increase/_models.py @@ -3,7 +3,20 @@ import os import inspect import weakref -from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, Optional, cast +from typing import ( + IO, + TYPE_CHECKING, + Any, + Type, + Union, + Generic, + TypeVar, + Callable, + Iterable, + Optional, + AsyncIterable, + cast, +) from datetime import date, datetime from typing_extensions import ( List, @@ -787,6 +800,7 @@ class FinalRequestOptionsInput(TypedDict, total=False): timeout: float | Timeout | None files: HttpxRequestFiles | None idempotency_key: str + content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] json_data: Body extra_json: AnyMapping follow_redirects: bool @@ -805,6 +819,7 @@ class FinalRequestOptions(pydantic.BaseModel): post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() follow_redirects: Union[bool, None] = None + content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None # It should be noted that we cannot use `json` here as that would override # a BaseModel method in an incompatible fashion. json_data: Union[Body, None] = None diff --git a/src/increase/_response.py b/src/increase/_response.py index 7fb2fb75a..b64b589d6 100644 --- a/src/increase/_response.py +++ b/src/increase/_response.py @@ -152,6 +152,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: ), response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -162,6 +163,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to=extract_stream_chunk_type(self._stream_cls), response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -175,6 +177,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -268,6 +271,10 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: class APIResponse(BaseAPIResponse[R]): + @property + def idempotent_replayed(self) -> str | None: + return self.http_response.headers.get("Idempotent-Replayed") # type: ignore[no-any-return] + @overload def parse(self, *, to: type[_T]) -> _T: ... @@ -370,6 +377,10 @@ def iter_lines(self) -> Iterator[str]: class AsyncAPIResponse(BaseAPIResponse[R]): + @property + def idempotent_replayed(self) -> str | None: + return self.http_response.headers.get("Idempotent-Replayed") # type: ignore[no-any-return] + @overload async def parse(self, *, to: type[_T]) -> _T: ... diff --git a/src/increase/_streaming.py b/src/increase/_streaming.py index 48bbc2c53..93e15346d 100644 --- a/src/increase/_streaming.py +++ b/src/increase/_streaming.py @@ -4,7 +4,7 @@ import json import inspect from types import TracebackType -from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, AsyncIterator, cast +from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, Optional, AsyncIterator, cast from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable import httpx @@ -13,6 +13,7 @@ if TYPE_CHECKING: from ._client import Increase, AsyncIncrease + from ._models import FinalRequestOptions _T = TypeVar("_T") @@ -22,7 +23,7 @@ class Stream(Generic[_T]): """Provides the core interface to iterate over a synchronous stream response.""" response: httpx.Response - + _options: Optional[FinalRequestOptions] = None _decoder: SSEBytesDecoder def __init__( @@ -31,10 +32,12 @@ def __init__( cast_to: type[_T], response: httpx.Response, client: Increase, + options: Optional[FinalRequestOptions] = None, ) -> None: self.response = response self._cast_to = cast_to self._client = client + self._options = options self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() @@ -85,7 +88,7 @@ class AsyncStream(Generic[_T]): """Provides the core interface to iterate over an asynchronous stream response.""" response: httpx.Response - + _options: Optional[FinalRequestOptions] = None _decoder: SSEDecoder | SSEBytesDecoder def __init__( @@ -94,10 +97,12 @@ def __init__( cast_to: type[_T], response: httpx.Response, client: AsyncIncrease, + options: Optional[FinalRequestOptions] = None, ) -> None: self.response = response self._cast_to = cast_to self._client = client + self._options = options self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() diff --git a/src/increase/_types.py b/src/increase/_types.py index d9b38629d..41865091f 100644 --- a/src/increase/_types.py +++ b/src/increase/_types.py @@ -13,9 +13,11 @@ Mapping, TypeVar, Callable, + Iterable, Iterator, Optional, Sequence, + AsyncIterable, ) from typing_extensions import ( Set, @@ -56,6 +58,13 @@ else: Base64FileInput = Union[IO[bytes], PathLike] FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8. + + +# Used for sending raw binary data / streaming data in request bodies +# e.g. for file uploads without multipart encoding +BinaryTypes = Union[bytes, bytearray, IO[bytes], Iterable[bytes]] +AsyncBinaryTypes = Union[bytes, bytearray, IO[bytes], AsyncIterable[bytes]] + FileTypes = Union[ # file (or bytes) FileContent, diff --git a/src/increase/_utils/_compat.py b/src/increase/_utils/_compat.py index dd703233c..2c70b299c 100644 --- a/src/increase/_utils/_compat.py +++ b/src/increase/_utils/_compat.py @@ -26,7 +26,7 @@ def is_union(tp: Optional[Type[Any]]) -> bool: else: import types - return tp is Union or tp is types.UnionType + return tp is Union or tp is types.UnionType # type: ignore[comparison-overlap] def is_typeddict(tp: Type[Any]) -> bool: diff --git a/src/increase/_utils/_json.py b/src/increase/_utils/_json.py new file mode 100644 index 000000000..60584214a --- /dev/null +++ b/src/increase/_utils/_json.py @@ -0,0 +1,35 @@ +import json +from typing import Any +from datetime import datetime +from typing_extensions import override + +import pydantic + +from .._compat import model_dump + + +def openapi_dumps(obj: Any) -> bytes: + """ + Serialize an object to UTF-8 encoded JSON bytes. + + Extends the standard json.dumps with support for additional types + commonly used in the SDK, such as `datetime`, `pydantic.BaseModel`, etc. + """ + return json.dumps( + obj, + cls=_CustomEncoder, + # Uses the same defaults as httpx's JSON serialization + ensure_ascii=False, + separators=(",", ":"), + allow_nan=False, + ).encode() + + +class _CustomEncoder(json.JSONEncoder): + @override + def default(self, o: Any) -> Any: + if isinstance(o, datetime): + return o.isoformat() + if isinstance(o, pydantic.BaseModel): + return model_dump(o, exclude_unset=True, mode="json", by_alias=True) + return super().default(o) diff --git a/src/increase/_version.py b/src/increase/_version.py index 1a1e8d6a1..136fa3d00 100644 --- a/src/increase/_version.py +++ b/src/increase/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "increase" -__version__ = "0.423.0" # x-release-please-version +__version__ = "0.424.0" # x-release-please-version diff --git a/src/increase/resources/__init__.py b/src/increase/resources/__init__.py index 24c33f0ba..db5c50a25 100644 --- a/src/increase/resources/__init__.py +++ b/src/increase/resources/__init__.py @@ -185,6 +185,14 @@ RoutingNumbersResourceWithStreamingResponse, AsyncRoutingNumbersResourceWithStreamingResponse, ) +from .swift_transfers import ( + SwiftTransfersResource, + AsyncSwiftTransfersResource, + SwiftTransfersResourceWithRawResponse, + AsyncSwiftTransfersResourceWithRawResponse, + SwiftTransfersResourceWithStreamingResponse, + AsyncSwiftTransfersResourceWithStreamingResponse, +) from .card_validations import ( CardValidationsResource, AsyncCardValidationsResource, @@ -615,6 +623,12 @@ "AsyncInboundFednowTransfersResourceWithRawResponse", "InboundFednowTransfersResourceWithStreamingResponse", "AsyncInboundFednowTransfersResourceWithStreamingResponse", + "SwiftTransfersResource", + "AsyncSwiftTransfersResource", + "SwiftTransfersResourceWithRawResponse", + "AsyncSwiftTransfersResourceWithRawResponse", + "SwiftTransfersResourceWithStreamingResponse", + "AsyncSwiftTransfersResourceWithStreamingResponse", "CheckDepositsResource", "AsyncCheckDepositsResource", "CheckDepositsResourceWithRawResponse", diff --git a/src/increase/resources/accounts.py b/src/increase/resources/accounts.py index 080ab2bf6..7fe998692 100644 --- a/src/increase/resources/accounts.py +++ b/src/increase/resources/accounts.py @@ -4,6 +4,7 @@ from typing import Union from datetime import datetime +from typing_extensions import Literal import httpx @@ -51,7 +52,9 @@ def create( *, name: str, entity_id: str | Omit = omit, + funding: Literal["loan", "deposits"] | Omit = omit, informational_entity_id: str | Omit = omit, + loan: account_create_params.Loan | Omit = omit, program_id: str | 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. @@ -69,9 +72,17 @@ def create( entity_id: The identifier for the Entity that will own the Account. + funding: Whether the Account is funded by a loan or by deposits. + + - `loan` - An account funded by a loan. Before opening a loan account, contact + support@increase.com to set up a loan program. + - `deposits` - An account funded by deposits. + informational_entity_id: The identifier of an Entity that, while not owning the Account, is associated with its activity. This is generally the beneficiary of the funds. + loan: The loan details for the account. + program_id: The identifier for the Program that this Account falls under. Required if you operate more than one Program. @@ -91,7 +102,9 @@ def create( { "name": name, "entity_id": entity_id, + "funding": funding, "informational_entity_id": informational_entity_id, + "loan": loan, "program_id": program_id, }, account_create_params.AccountCreateParams, @@ -145,7 +158,7 @@ def update( self, account_id: str, *, - credit_limit: int | Omit = omit, + loan: account_update_params.Loan | Omit = omit, name: str | 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. @@ -161,8 +174,7 @@ def update( Args: account_id: The identifier of the Account to update. - credit_limit: The new credit limit of the Account, if and only if the Account is a loan - account. + loan: The loan details for the account. name: The new name of the Account. @@ -182,7 +194,7 @@ def update( f"/accounts/{account_id}", body=maybe_transform( { - "credit_limit": credit_limit, + "loan": loan, "name": name, }, account_update_params.AccountUpdateParams, @@ -380,7 +392,9 @@ async def create( *, name: str, entity_id: str | Omit = omit, + funding: Literal["loan", "deposits"] | Omit = omit, informational_entity_id: str | Omit = omit, + loan: account_create_params.Loan | Omit = omit, program_id: str | 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. @@ -398,9 +412,17 @@ async def create( entity_id: The identifier for the Entity that will own the Account. + funding: Whether the Account is funded by a loan or by deposits. + + - `loan` - An account funded by a loan. Before opening a loan account, contact + support@increase.com to set up a loan program. + - `deposits` - An account funded by deposits. + informational_entity_id: The identifier of an Entity that, while not owning the Account, is associated with its activity. This is generally the beneficiary of the funds. + loan: The loan details for the account. + program_id: The identifier for the Program that this Account falls under. Required if you operate more than one Program. @@ -420,7 +442,9 @@ async def create( { "name": name, "entity_id": entity_id, + "funding": funding, "informational_entity_id": informational_entity_id, + "loan": loan, "program_id": program_id, }, account_create_params.AccountCreateParams, @@ -474,7 +498,7 @@ async def update( self, account_id: str, *, - credit_limit: int | Omit = omit, + loan: account_update_params.Loan | Omit = omit, name: str | 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. @@ -490,8 +514,7 @@ async def update( Args: account_id: The identifier of the Account to update. - credit_limit: The new credit limit of the Account, if and only if the Account is a loan - account. + loan: The loan details for the account. name: The new name of the Account. @@ -511,7 +534,7 @@ async def update( f"/accounts/{account_id}", body=await async_maybe_transform( { - "credit_limit": credit_limit, + "loan": loan, "name": name, }, account_update_params.AccountUpdateParams, diff --git a/src/increase/resources/ach_prenotifications.py b/src/increase/resources/ach_prenotifications.py index 7d2af5fe1..04c6bbdd5 100644 --- a/src/increase/resources/ach_prenotifications.py +++ b/src/increase/resources/ach_prenotifications.py @@ -110,12 +110,21 @@ def create( individual_name: The name of therecipient. This value is informational and not verified by the recipient's bank. - standard_entry_class_code: The Standard Entry Class (SEC) code to use for the ACH Prenotification. - - - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD). - - `corporate_trade_exchange` - Corporate Trade Exchange (CTX). - - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD). - - `internet_initiated` - Internet Initiated (WEB). + standard_entry_class_code: The + [Standard Entry Class (SEC) code](/documentation/ach-standard-entry-class-codes) + to use for the ACH Prenotification. + + - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD) is used for + business-to-business payments. + - `corporate_trade_exchange` - Corporate Trade Exchange (CTX) allows for + including extensive remittance information with business-to-business payments. + - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD) + is used for credits or debits originated by an organization to a consumer, + such as payroll direct deposits. + - `internet_initiated` - Internet Initiated (WEB) is used for consumer payments + initiated or authorized via the Internet. Debits can only be initiated by + non-consumers to debit a consumer’s account. Credits can only be used for + consumer to consumer transactions. extra_headers: Send extra headers @@ -336,12 +345,21 @@ async def create( individual_name: The name of therecipient. This value is informational and not verified by the recipient's bank. - standard_entry_class_code: The Standard Entry Class (SEC) code to use for the ACH Prenotification. - - - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD). - - `corporate_trade_exchange` - Corporate Trade Exchange (CTX). - - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD). - - `internet_initiated` - Internet Initiated (WEB). + standard_entry_class_code: The + [Standard Entry Class (SEC) code](/documentation/ach-standard-entry-class-codes) + to use for the ACH Prenotification. + + - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD) is used for + business-to-business payments. + - `corporate_trade_exchange` - Corporate Trade Exchange (CTX) allows for + including extensive remittance information with business-to-business payments. + - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD) + is used for credits or debits originated by an organization to a consumer, + such as payroll direct deposits. + - `internet_initiated` - Internet Initiated (WEB) is used for consumer payments + initiated or authorized via the Internet. Debits can only be initiated by + non-consumers to debit a consumer’s account. Credits can only be used for + consumer to consumer transactions. extra_headers: Send extra headers diff --git a/src/increase/resources/ach_transfers.py b/src/increase/resources/ach_transfers.py index d07b5534a..04b4d624b 100644 --- a/src/increase/resources/ach_transfers.py +++ b/src/increase/resources/ach_transfers.py @@ -108,8 +108,9 @@ def create( company_discretionary_data: The data you choose to associate with the transfer. This is included in the transfer data sent to the receiving bank. - company_entry_description: A description of the transfer. This is included in the transfer data sent to the - receiving bank. + company_entry_description: A description of the transfer, included in the transfer data sent to the + receiving bank. Standardized formatting may be required, for example `PAYROLL` + for payroll-related Prearranged Payments and Deposits (PPD) credit transfers. company_name: The name by which the recipient knows you. This is included in the transfer data sent to the receiving bank. @@ -145,12 +146,21 @@ def create( routing_number: The American Bankers' Association (ABA) Routing Transit Number (RTN) for the destination account. - standard_entry_class_code: The Standard Entry Class (SEC) code to use for the transfer. - - - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD). - - `corporate_trade_exchange` - Corporate Trade Exchange (CTX). - - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD). - - `internet_initiated` - Internet Initiated (WEB). + standard_entry_class_code: The + [Standard Entry Class (SEC) code](/documentation/ach-standard-entry-class-codes) + to use for the transfer. + + - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD) is used for + business-to-business payments. + - `corporate_trade_exchange` - Corporate Trade Exchange (CTX) allows for + including extensive remittance information with business-to-business payments. + - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD) + is used for credits or debits originated by an organization to a consumer, + such as payroll direct deposits. + - `internet_initiated` - Internet Initiated (WEB) is used for consumer payments + initiated or authorized via the Internet. Debits can only be initiated by + non-consumers to debit a consumer’s account. Credits can only be used for + consumer to consumer transactions. transaction_timing: The timing of the transaction. @@ -475,8 +485,9 @@ async def create( company_discretionary_data: The data you choose to associate with the transfer. This is included in the transfer data sent to the receiving bank. - company_entry_description: A description of the transfer. This is included in the transfer data sent to the - receiving bank. + company_entry_description: A description of the transfer, included in the transfer data sent to the + receiving bank. Standardized formatting may be required, for example `PAYROLL` + for payroll-related Prearranged Payments and Deposits (PPD) credit transfers. company_name: The name by which the recipient knows you. This is included in the transfer data sent to the receiving bank. @@ -512,12 +523,21 @@ async def create( routing_number: The American Bankers' Association (ABA) Routing Transit Number (RTN) for the destination account. - standard_entry_class_code: The Standard Entry Class (SEC) code to use for the transfer. - - - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD). - - `corporate_trade_exchange` - Corporate Trade Exchange (CTX). - - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD). - - `internet_initiated` - Internet Initiated (WEB). + standard_entry_class_code: The + [Standard Entry Class (SEC) code](/documentation/ach-standard-entry-class-codes) + to use for the transfer. + + - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD) is used for + business-to-business payments. + - `corporate_trade_exchange` - Corporate Trade Exchange (CTX) allows for + including extensive remittance information with business-to-business payments. + - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD) + is used for credits or debits originated by an organization to a consumer, + such as payroll direct deposits. + - `internet_initiated` - Internet Initiated (WEB) is used for consumer payments + initiated or authorized via the Internet. Debits can only be initiated by + non-consumers to debit a consumer’s account. Credits can only be used for + consumer to consumer transactions. transaction_timing: The timing of the transaction. diff --git a/src/increase/resources/card_disputes.py b/src/increase/resources/card_disputes.py index f5aea9266..bfdbc27e1 100644 --- a/src/increase/resources/card_disputes.py +++ b/src/increase/resources/card_disputes.py @@ -7,7 +7,12 @@ import httpx -from ..types import card_dispute_list_params, card_dispute_create_params, card_dispute_submit_user_submission_params +from ..types import ( + card_dispute_list_params, + card_dispute_create_params, + card_dispute_withdraw_params, + card_dispute_submit_user_submission_params, +) from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property @@ -293,6 +298,7 @@ def withdraw( self, card_dispute_id: str, *, + explanation: str | 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, @@ -307,6 +313,8 @@ def withdraw( Args: card_dispute_id: The identifier of the Card Dispute to withdraw. + explanation: The explanation for withdrawing the Card Dispute. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -321,6 +329,7 @@ def withdraw( raise ValueError(f"Expected a non-empty value for `card_dispute_id` but received {card_dispute_id!r}") return self._post( f"/card_disputes/{card_dispute_id}/withdraw", + body=maybe_transform({"explanation": explanation}, card_dispute_withdraw_params.CardDisputeWithdrawParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -600,6 +609,7 @@ async def withdraw( self, card_dispute_id: str, *, + explanation: str | 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, @@ -614,6 +624,8 @@ async def withdraw( Args: card_dispute_id: The identifier of the Card Dispute to withdraw. + explanation: The explanation for withdrawing the Card Dispute. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -628,6 +640,9 @@ async def withdraw( raise ValueError(f"Expected a non-empty value for `card_dispute_id` but received {card_dispute_id!r}") return await self._post( f"/card_disputes/{card_dispute_id}/withdraw", + body=await async_maybe_transform( + {"explanation": explanation}, card_dispute_withdraw_params.CardDisputeWithdrawParams + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, diff --git a/src/increase/resources/entities.py b/src/increase/resources/entities.py index 016f4d84d..19c079d72 100644 --- a/src/increase/resources/entities.py +++ b/src/increase/resources/entities.py @@ -12,9 +12,6 @@ entity_list_params, entity_create_params, entity_update_params, - entity_confirm_params, - entity_update_address_params, - entity_update_industry_code_params, entity_create_beneficial_owner_params, entity_archive_beneficial_owner_params, entity_update_beneficial_owner_address_params, @@ -106,7 +103,7 @@ def create( `social_security_number` or `individual_taxpayer_identification_number` identification methods. - risk_rating: An assessment of the entity’s potential risk of involvement in financial crimes, + risk_rating: An assessment of the entity's potential risk of involvement in financial crimes, such as money laundering. supplemental_documents: Additional documentation associated with the entity. @@ -432,55 +429,6 @@ def archive_beneficial_owner( cast_to=Entity, ) - def confirm( - self, - entity_id: str, - *, - confirmed_at: Union[str, datetime] | 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, - idempotency_key: str | None = None, - ) -> Entity: - """ - Depending on your program, you may be required to re-confirm an Entity's details - on a recurring basis. After making any required updates, call this endpoint to - record that your user confirmed their details. - - Args: - entity_id: The identifier of the Entity to confirm the details of. - - confirmed_at: When your user confirmed the Entity's details. If not provided, the current time - will be used. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not entity_id: - raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}") - return self._post( - f"/entities/{entity_id}/confirm", - body=maybe_transform({"confirmed_at": confirmed_at}, entity_confirm_params.EntityConfirmParams), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Entity, - ) - def create_beneficial_owner( self, entity_id: str, @@ -531,53 +479,6 @@ def create_beneficial_owner( cast_to=Entity, ) - def update_address( - self, - entity_id: str, - *, - address: entity_update_address_params.Address, - # 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, - idempotency_key: str | None = None, - ) -> Entity: - """ - Update a Natural Person or Corporation's address - - Args: - entity_id: The identifier of the Entity whose address is being updated. - - address: The entity's physical address. Mail receiving locations like PO Boxes and PMB's - are disallowed. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not entity_id: - raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}") - return self._post( - f"/entities/{entity_id}/update_address", - body=maybe_transform({"address": address}, entity_update_address_params.EntityUpdateAddressParams), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Entity, - ) - def update_beneficial_owner_address( self, entity_id: str, @@ -636,58 +537,6 @@ def update_beneficial_owner_address( cast_to=Entity, ) - def update_industry_code( - self, - entity_id: str, - *, - industry_code: str, - # 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, - idempotency_key: str | None = None, - ) -> Entity: - """ - Update the industry code for a corporate Entity - - Args: - entity_id: The identifier of the Entity to update. This endpoint only accepts `corporation` - entities. - - industry_code: The North American Industry Classification System (NAICS) code for the - corporation's primary line of business. This is a number, like `5132` for - `Software Publishers`. A full list of classification codes is available - [here](https://increase.com/documentation/data-dictionary#north-american-industry-classification-system-codes). - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not entity_id: - raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}") - return self._post( - f"/entities/{entity_id}/update_industry_code", - body=maybe_transform( - {"industry_code": industry_code}, entity_update_industry_code_params.EntityUpdateIndustryCodeParams - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Entity, - ) - class AsyncEntitiesResource(AsyncAPIResource): @cached_property @@ -759,7 +608,7 @@ async def create( `social_security_number` or `individual_taxpayer_identification_number` identification methods. - risk_rating: An assessment of the entity’s potential risk of involvement in financial crimes, + risk_rating: An assessment of the entity's potential risk of involvement in financial crimes, such as money laundering. supplemental_documents: Additional documentation associated with the entity. @@ -1085,55 +934,6 @@ async def archive_beneficial_owner( cast_to=Entity, ) - async def confirm( - self, - entity_id: str, - *, - confirmed_at: Union[str, datetime] | 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, - idempotency_key: str | None = None, - ) -> Entity: - """ - Depending on your program, you may be required to re-confirm an Entity's details - on a recurring basis. After making any required updates, call this endpoint to - record that your user confirmed their details. - - Args: - entity_id: The identifier of the Entity to confirm the details of. - - confirmed_at: When your user confirmed the Entity's details. If not provided, the current time - will be used. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not entity_id: - raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}") - return await self._post( - f"/entities/{entity_id}/confirm", - body=await async_maybe_transform({"confirmed_at": confirmed_at}, entity_confirm_params.EntityConfirmParams), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Entity, - ) - async def create_beneficial_owner( self, entity_id: str, @@ -1184,55 +984,6 @@ async def create_beneficial_owner( cast_to=Entity, ) - async def update_address( - self, - entity_id: str, - *, - address: entity_update_address_params.Address, - # 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, - idempotency_key: str | None = None, - ) -> Entity: - """ - Update a Natural Person or Corporation's address - - Args: - entity_id: The identifier of the Entity whose address is being updated. - - address: The entity's physical address. Mail receiving locations like PO Boxes and PMB's - are disallowed. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not entity_id: - raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}") - return await self._post( - f"/entities/{entity_id}/update_address", - body=await async_maybe_transform( - {"address": address}, entity_update_address_params.EntityUpdateAddressParams - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Entity, - ) - async def update_beneficial_owner_address( self, entity_id: str, @@ -1291,58 +1042,6 @@ async def update_beneficial_owner_address( cast_to=Entity, ) - async def update_industry_code( - self, - entity_id: str, - *, - industry_code: str, - # 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, - idempotency_key: str | None = None, - ) -> Entity: - """ - Update the industry code for a corporate Entity - - Args: - entity_id: The identifier of the Entity to update. This endpoint only accepts `corporation` - entities. - - industry_code: The North American Industry Classification System (NAICS) code for the - corporation's primary line of business. This is a number, like `5132` for - `Software Publishers`. A full list of classification codes is available - [here](https://increase.com/documentation/data-dictionary#north-american-industry-classification-system-codes). - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not entity_id: - raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}") - return await self._post( - f"/entities/{entity_id}/update_industry_code", - body=await async_maybe_transform( - {"industry_code": industry_code}, entity_update_industry_code_params.EntityUpdateIndustryCodeParams - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Entity, - ) - class EntitiesResourceWithRawResponse: def __init__(self, entities: EntitiesResource) -> None: @@ -1366,21 +1065,12 @@ def __init__(self, entities: EntitiesResource) -> None: self.archive_beneficial_owner = to_raw_response_wrapper( entities.archive_beneficial_owner, ) - self.confirm = to_raw_response_wrapper( - entities.confirm, - ) self.create_beneficial_owner = to_raw_response_wrapper( entities.create_beneficial_owner, ) - self.update_address = to_raw_response_wrapper( - entities.update_address, - ) self.update_beneficial_owner_address = to_raw_response_wrapper( entities.update_beneficial_owner_address, ) - self.update_industry_code = to_raw_response_wrapper( - entities.update_industry_code, - ) class AsyncEntitiesResourceWithRawResponse: @@ -1405,21 +1095,12 @@ def __init__(self, entities: AsyncEntitiesResource) -> None: self.archive_beneficial_owner = async_to_raw_response_wrapper( entities.archive_beneficial_owner, ) - self.confirm = async_to_raw_response_wrapper( - entities.confirm, - ) self.create_beneficial_owner = async_to_raw_response_wrapper( entities.create_beneficial_owner, ) - self.update_address = async_to_raw_response_wrapper( - entities.update_address, - ) self.update_beneficial_owner_address = async_to_raw_response_wrapper( entities.update_beneficial_owner_address, ) - self.update_industry_code = async_to_raw_response_wrapper( - entities.update_industry_code, - ) class EntitiesResourceWithStreamingResponse: @@ -1444,21 +1125,12 @@ def __init__(self, entities: EntitiesResource) -> None: self.archive_beneficial_owner = to_streamed_response_wrapper( entities.archive_beneficial_owner, ) - self.confirm = to_streamed_response_wrapper( - entities.confirm, - ) self.create_beneficial_owner = to_streamed_response_wrapper( entities.create_beneficial_owner, ) - self.update_address = to_streamed_response_wrapper( - entities.update_address, - ) self.update_beneficial_owner_address = to_streamed_response_wrapper( entities.update_beneficial_owner_address, ) - self.update_industry_code = to_streamed_response_wrapper( - entities.update_industry_code, - ) class AsyncEntitiesResourceWithStreamingResponse: @@ -1483,18 +1155,9 @@ def __init__(self, entities: AsyncEntitiesResource) -> None: self.archive_beneficial_owner = async_to_streamed_response_wrapper( entities.archive_beneficial_owner, ) - self.confirm = async_to_streamed_response_wrapper( - entities.confirm, - ) self.create_beneficial_owner = async_to_streamed_response_wrapper( entities.create_beneficial_owner, ) - self.update_address = async_to_streamed_response_wrapper( - entities.update_address, - ) self.update_beneficial_owner_address = async_to_streamed_response_wrapper( entities.update_beneficial_owner_address, ) - self.update_industry_code = async_to_streamed_response_wrapper( - entities.update_industry_code, - ) diff --git a/src/increase/resources/event_subscriptions.py b/src/increase/resources/event_subscriptions.py index a732bbfce..c7840b0d6 100644 --- a/src/increase/resources/event_subscriptions.py +++ b/src/increase/resources/event_subscriptions.py @@ -2,6 +2,7 @@ from __future__ import annotations +from typing import Iterable from typing_extensions import Literal import httpx @@ -49,110 +50,7 @@ def create( *, url: str, oauth_connection_id: str | Omit = omit, - selected_event_category: Literal[ - "account.created", - "account.updated", - "account_number.created", - "account_number.updated", - "account_statement.created", - "account_transfer.created", - "account_transfer.updated", - "ach_prenotification.created", - "ach_prenotification.updated", - "ach_transfer.created", - "ach_transfer.updated", - "bookkeeping_account.created", - "bookkeeping_account.updated", - "bookkeeping_entry_set.updated", - "card.created", - "card.updated", - "card_payment.created", - "card_payment.updated", - "card_profile.created", - "card_profile.updated", - "card_dispute.created", - "card_dispute.updated", - "check_deposit.created", - "check_deposit.updated", - "check_transfer.created", - "check_transfer.updated", - "declined_transaction.created", - "digital_card_profile.created", - "digital_card_profile.updated", - "digital_wallet_token.created", - "digital_wallet_token.updated", - "document.created", - "entity.created", - "entity.updated", - "event_subscription.created", - "event_subscription.updated", - "export.created", - "export.updated", - "external_account.created", - "external_account.updated", - "fednow_transfer.created", - "fednow_transfer.updated", - "file.created", - "group.updated", - "group.heartbeat", - "inbound_ach_transfer.created", - "inbound_ach_transfer.updated", - "inbound_ach_transfer_return.created", - "inbound_ach_transfer_return.updated", - "inbound_check_deposit.created", - "inbound_check_deposit.updated", - "inbound_fednow_transfer.created", - "inbound_fednow_transfer.updated", - "inbound_mail_item.created", - "inbound_mail_item.updated", - "inbound_real_time_payments_transfer.created", - "inbound_real_time_payments_transfer.updated", - "inbound_wire_drawdown_request.created", - "inbound_wire_transfer.created", - "inbound_wire_transfer.updated", - "intrafi_account_enrollment.created", - "intrafi_account_enrollment.updated", - "intrafi_exclusion.created", - "intrafi_exclusion.updated", - "legacy_card_dispute.created", - "legacy_card_dispute.updated", - "lockbox.created", - "lockbox.updated", - "oauth_connection.created", - "oauth_connection.deactivated", - "card_push_transfer.created", - "card_push_transfer.updated", - "card_validation.created", - "card_validation.updated", - "pending_transaction.created", - "pending_transaction.updated", - "physical_card.created", - "physical_card.updated", - "physical_card_profile.created", - "physical_card_profile.updated", - "program.created", - "program.updated", - "proof_of_authorization_request.created", - "proof_of_authorization_request.updated", - "real_time_decision.card_authorization_requested", - "real_time_decision.card_balance_inquiry_requested", - "real_time_decision.digital_wallet_token_requested", - "real_time_decision.digital_wallet_authentication_requested", - "real_time_decision.card_authentication_requested", - "real_time_decision.card_authentication_challenge_requested", - "real_time_payments_transfer.created", - "real_time_payments_transfer.updated", - "real_time_payments_request_for_payment.created", - "real_time_payments_request_for_payment.updated", - "swift_transfer.created", - "swift_transfer.updated", - "transaction.created", - "wire_drawdown_request.created", - "wire_drawdown_request.updated", - "wire_transfer.created", - "wire_transfer.updated", - ] - | Omit = omit, + selected_event_categories: Iterable[event_subscription_create_params.SelectedEventCategory] | Omit = omit, shared_secret: str | Omit = omit, status: Literal["active", "disabled"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -172,163 +70,9 @@ def create( oauth_connection_id: If specified, this subscription will only receive webhooks for Events associated with the specified OAuth Connection. - selected_event_category: If specified, this subscription will only receive webhooks for Events with the - specified `category`. - - - `account.created` - Occurs whenever an Account is created. - - `account.updated` - Occurs whenever an Account is updated. - - `account_number.created` - Occurs whenever an Account Number is created. - - `account_number.updated` - Occurs whenever an Account Number is updated. - - `account_statement.created` - Occurs whenever an Account Statement is created. - - `account_transfer.created` - Occurs whenever an Account Transfer is created. - - `account_transfer.updated` - Occurs whenever an Account Transfer is updated. - - `ach_prenotification.created` - Occurs whenever an ACH Prenotification is - created. - - `ach_prenotification.updated` - Occurs whenever an ACH Prenotification is - updated. - - `ach_transfer.created` - Occurs whenever an ACH Transfer is created. - - `ach_transfer.updated` - Occurs whenever an ACH Transfer is updated. - - `bookkeeping_account.created` - Occurs whenever a Bookkeeping Account is - created. - - `bookkeeping_account.updated` - Occurs whenever a Bookkeeping Account is - updated. - - `bookkeeping_entry_set.updated` - Occurs whenever a Bookkeeping Entry Set is - created. - - `card.created` - Occurs whenever a Card is created. - - `card.updated` - Occurs whenever a Card is updated. - - `card_payment.created` - Occurs whenever a Card Payment is created. - - `card_payment.updated` - Occurs whenever a Card Payment is updated. - - `card_profile.created` - Occurs whenever a Card Profile is created. - - `card_profile.updated` - Occurs whenever a Card Profile is updated. - - `card_dispute.created` - Occurs whenever a Card Dispute is created. - - `card_dispute.updated` - Occurs whenever a Card Dispute is updated. - - `check_deposit.created` - Occurs whenever a Check Deposit is created. - - `check_deposit.updated` - Occurs whenever a Check Deposit is updated. - - `check_transfer.created` - Occurs whenever a Check Transfer is created. - - `check_transfer.updated` - Occurs whenever a Check Transfer is updated. - - `declined_transaction.created` - Occurs whenever a Declined Transaction is - created. - - `digital_card_profile.created` - Occurs whenever a Digital Card Profile is - created. - - `digital_card_profile.updated` - Occurs whenever a Digital Card Profile is - updated. - - `digital_wallet_token.created` - Occurs whenever a Digital Wallet Token is - created. - - `digital_wallet_token.updated` - Occurs whenever a Digital Wallet Token is - updated. - - `document.created` - Occurs whenever a Document is created. - - `entity.created` - Occurs whenever an Entity is created. - - `entity.updated` - Occurs whenever an Entity is updated. - - `event_subscription.created` - Occurs whenever an Event Subscription is - created. - - `event_subscription.updated` - Occurs whenever an Event Subscription is - updated. - - `export.created` - Occurs whenever an Export is created. - - `export.updated` - Occurs whenever an Export is updated. - - `external_account.created` - Occurs whenever an External Account is created. - - `external_account.updated` - Occurs whenever an External Account is updated. - - `fednow_transfer.created` - Occurs whenever a FedNow Transfer is created. - - `fednow_transfer.updated` - Occurs whenever a FedNow Transfer is updated. - - `file.created` - Occurs whenever a File is created. - - `group.updated` - Occurs whenever a Group is updated. - - `group.heartbeat` - Increase may send webhooks with this category to see if a - webhook endpoint is working properly. - - `inbound_ach_transfer.created` - Occurs whenever an Inbound ACH Transfer is - created. - - `inbound_ach_transfer.updated` - Occurs whenever an Inbound ACH Transfer is - updated. - - `inbound_ach_transfer_return.created` - Occurs whenever an Inbound ACH - Transfer Return is created. - - `inbound_ach_transfer_return.updated` - Occurs whenever an Inbound ACH - Transfer Return is updated. - - `inbound_check_deposit.created` - Occurs whenever an Inbound Check Deposit is - created. - - `inbound_check_deposit.updated` - Occurs whenever an Inbound Check Deposit is - updated. - - `inbound_fednow_transfer.created` - Occurs whenever an Inbound FedNow Transfer - is created. - - `inbound_fednow_transfer.updated` - Occurs whenever an Inbound FedNow Transfer - is updated. - - `inbound_mail_item.created` - Occurs whenever an Inbound Mail Item is created. - - `inbound_mail_item.updated` - Occurs whenever an Inbound Mail Item is updated. - - `inbound_real_time_payments_transfer.created` - Occurs whenever an Inbound - Real-Time Payments Transfer is created. - - `inbound_real_time_payments_transfer.updated` - Occurs whenever an Inbound - Real-Time Payments Transfer is updated. - - `inbound_wire_drawdown_request.created` - Occurs whenever an Inbound Wire - Drawdown Request is created. - - `inbound_wire_transfer.created` - Occurs whenever an Inbound Wire Transfer is - created. - - `inbound_wire_transfer.updated` - Occurs whenever an Inbound Wire Transfer is - updated. - - `intrafi_account_enrollment.created` - Occurs whenever an IntraFi Account - Enrollment is created. - - `intrafi_account_enrollment.updated` - Occurs whenever an IntraFi Account - Enrollment is updated. - - `intrafi_exclusion.created` - Occurs whenever an IntraFi Exclusion is created. - - `intrafi_exclusion.updated` - Occurs whenever an IntraFi Exclusion is updated. - - `legacy_card_dispute.created` - Occurs whenever a Legacy Card Dispute is - created. - - `legacy_card_dispute.updated` - Occurs whenever a Legacy Card Dispute is - updated. - - `lockbox.created` - Occurs whenever a Lockbox is created. - - `lockbox.updated` - Occurs whenever a Lockbox is updated. - - `oauth_connection.created` - Occurs whenever an OAuth Connection is created. - - `oauth_connection.deactivated` - Occurs whenever an OAuth Connection is - deactivated. - - `card_push_transfer.created` - Occurs whenever a Card Push Transfer is - created. - - `card_push_transfer.updated` - Occurs whenever a Card Push Transfer is - updated. - - `card_validation.created` - Occurs whenever a Card Validation is created. - - `card_validation.updated` - Occurs whenever a Card Validation is updated. - - `pending_transaction.created` - Occurs whenever a Pending Transaction is - created. - - `pending_transaction.updated` - Occurs whenever a Pending Transaction is - updated. - - `physical_card.created` - Occurs whenever a Physical Card is created. - - `physical_card.updated` - Occurs whenever a Physical Card is updated. - - `physical_card_profile.created` - Occurs whenever a Physical Card Profile is - created. - - `physical_card_profile.updated` - Occurs whenever a Physical Card Profile is - updated. - - `program.created` - Occurs whenever a Program is created. - - `program.updated` - Occurs whenever a Program is updated. - - `proof_of_authorization_request.created` - Occurs whenever a Proof of - Authorization Request is created. - - `proof_of_authorization_request.updated` - Occurs whenever a Proof of - Authorization Request is updated. - - `real_time_decision.card_authorization_requested` - Occurs whenever a - Real-Time Decision is created in response to a card authorization. - - `real_time_decision.card_balance_inquiry_requested` - Occurs whenever a - Real-Time Decision is created in response to a card balance inquiry. - - `real_time_decision.digital_wallet_token_requested` - Occurs whenever a - Real-Time Decision is created in response to a digital wallet provisioning - attempt. - - `real_time_decision.digital_wallet_authentication_requested` - Occurs whenever - a Real-Time Decision is created in response to a digital wallet requiring - two-factor authentication. - - `real_time_decision.card_authentication_requested` - Occurs whenever a - Real-Time Decision is created in response to 3DS authentication. - - `real_time_decision.card_authentication_challenge_requested` - Occurs whenever - a Real-Time Decision is created in response to 3DS authentication challenges. - - `real_time_payments_transfer.created` - Occurs whenever a Real-Time Payments - Transfer is created. - - `real_time_payments_transfer.updated` - Occurs whenever a Real-Time Payments - Transfer is updated. - - `real_time_payments_request_for_payment.created` - Occurs whenever a Real-Time - Payments Request for Payment is created. - - `real_time_payments_request_for_payment.updated` - Occurs whenever a Real-Time - Payments Request for Payment is updated. - - `swift_transfer.created` - Occurs whenever a Swift Transfer is created. - - `swift_transfer.updated` - Occurs whenever a Swift Transfer is updated. - - `transaction.created` - Occurs whenever a Transaction is created. - - `wire_drawdown_request.created` - Occurs whenever a Wire Drawdown Request is - created. - - `wire_drawdown_request.updated` - Occurs whenever a Wire Drawdown Request is - updated. - - `wire_transfer.created` - Occurs whenever a Wire Transfer is created. - - `wire_transfer.updated` - Occurs whenever a Wire Transfer is updated. + selected_event_categories: If specified, this subscription will only receive webhooks for Events with the + specified `category`. If specifying a Real-Time Decision event category, only + one Event Category can be specified for the Event Subscription. shared_secret: The key that will be used to sign webhooks. If no value is passed, a random string will be used as default. @@ -355,7 +99,7 @@ def create( { "url": url, "oauth_connection_id": oauth_connection_id, - "selected_event_category": selected_event_category, + "selected_event_categories": selected_event_categories, "shared_secret": shared_secret, "status": status, }, @@ -543,110 +287,7 @@ async def create( *, url: str, oauth_connection_id: str | Omit = omit, - selected_event_category: Literal[ - "account.created", - "account.updated", - "account_number.created", - "account_number.updated", - "account_statement.created", - "account_transfer.created", - "account_transfer.updated", - "ach_prenotification.created", - "ach_prenotification.updated", - "ach_transfer.created", - "ach_transfer.updated", - "bookkeeping_account.created", - "bookkeeping_account.updated", - "bookkeeping_entry_set.updated", - "card.created", - "card.updated", - "card_payment.created", - "card_payment.updated", - "card_profile.created", - "card_profile.updated", - "card_dispute.created", - "card_dispute.updated", - "check_deposit.created", - "check_deposit.updated", - "check_transfer.created", - "check_transfer.updated", - "declined_transaction.created", - "digital_card_profile.created", - "digital_card_profile.updated", - "digital_wallet_token.created", - "digital_wallet_token.updated", - "document.created", - "entity.created", - "entity.updated", - "event_subscription.created", - "event_subscription.updated", - "export.created", - "export.updated", - "external_account.created", - "external_account.updated", - "fednow_transfer.created", - "fednow_transfer.updated", - "file.created", - "group.updated", - "group.heartbeat", - "inbound_ach_transfer.created", - "inbound_ach_transfer.updated", - "inbound_ach_transfer_return.created", - "inbound_ach_transfer_return.updated", - "inbound_check_deposit.created", - "inbound_check_deposit.updated", - "inbound_fednow_transfer.created", - "inbound_fednow_transfer.updated", - "inbound_mail_item.created", - "inbound_mail_item.updated", - "inbound_real_time_payments_transfer.created", - "inbound_real_time_payments_transfer.updated", - "inbound_wire_drawdown_request.created", - "inbound_wire_transfer.created", - "inbound_wire_transfer.updated", - "intrafi_account_enrollment.created", - "intrafi_account_enrollment.updated", - "intrafi_exclusion.created", - "intrafi_exclusion.updated", - "legacy_card_dispute.created", - "legacy_card_dispute.updated", - "lockbox.created", - "lockbox.updated", - "oauth_connection.created", - "oauth_connection.deactivated", - "card_push_transfer.created", - "card_push_transfer.updated", - "card_validation.created", - "card_validation.updated", - "pending_transaction.created", - "pending_transaction.updated", - "physical_card.created", - "physical_card.updated", - "physical_card_profile.created", - "physical_card_profile.updated", - "program.created", - "program.updated", - "proof_of_authorization_request.created", - "proof_of_authorization_request.updated", - "real_time_decision.card_authorization_requested", - "real_time_decision.card_balance_inquiry_requested", - "real_time_decision.digital_wallet_token_requested", - "real_time_decision.digital_wallet_authentication_requested", - "real_time_decision.card_authentication_requested", - "real_time_decision.card_authentication_challenge_requested", - "real_time_payments_transfer.created", - "real_time_payments_transfer.updated", - "real_time_payments_request_for_payment.created", - "real_time_payments_request_for_payment.updated", - "swift_transfer.created", - "swift_transfer.updated", - "transaction.created", - "wire_drawdown_request.created", - "wire_drawdown_request.updated", - "wire_transfer.created", - "wire_transfer.updated", - ] - | Omit = omit, + selected_event_categories: Iterable[event_subscription_create_params.SelectedEventCategory] | Omit = omit, shared_secret: str | Omit = omit, status: Literal["active", "disabled"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -666,163 +307,9 @@ async def create( oauth_connection_id: If specified, this subscription will only receive webhooks for Events associated with the specified OAuth Connection. - selected_event_category: If specified, this subscription will only receive webhooks for Events with the - specified `category`. - - - `account.created` - Occurs whenever an Account is created. - - `account.updated` - Occurs whenever an Account is updated. - - `account_number.created` - Occurs whenever an Account Number is created. - - `account_number.updated` - Occurs whenever an Account Number is updated. - - `account_statement.created` - Occurs whenever an Account Statement is created. - - `account_transfer.created` - Occurs whenever an Account Transfer is created. - - `account_transfer.updated` - Occurs whenever an Account Transfer is updated. - - `ach_prenotification.created` - Occurs whenever an ACH Prenotification is - created. - - `ach_prenotification.updated` - Occurs whenever an ACH Prenotification is - updated. - - `ach_transfer.created` - Occurs whenever an ACH Transfer is created. - - `ach_transfer.updated` - Occurs whenever an ACH Transfer is updated. - - `bookkeeping_account.created` - Occurs whenever a Bookkeeping Account is - created. - - `bookkeeping_account.updated` - Occurs whenever a Bookkeeping Account is - updated. - - `bookkeeping_entry_set.updated` - Occurs whenever a Bookkeeping Entry Set is - created. - - `card.created` - Occurs whenever a Card is created. - - `card.updated` - Occurs whenever a Card is updated. - - `card_payment.created` - Occurs whenever a Card Payment is created. - - `card_payment.updated` - Occurs whenever a Card Payment is updated. - - `card_profile.created` - Occurs whenever a Card Profile is created. - - `card_profile.updated` - Occurs whenever a Card Profile is updated. - - `card_dispute.created` - Occurs whenever a Card Dispute is created. - - `card_dispute.updated` - Occurs whenever a Card Dispute is updated. - - `check_deposit.created` - Occurs whenever a Check Deposit is created. - - `check_deposit.updated` - Occurs whenever a Check Deposit is updated. - - `check_transfer.created` - Occurs whenever a Check Transfer is created. - - `check_transfer.updated` - Occurs whenever a Check Transfer is updated. - - `declined_transaction.created` - Occurs whenever a Declined Transaction is - created. - - `digital_card_profile.created` - Occurs whenever a Digital Card Profile is - created. - - `digital_card_profile.updated` - Occurs whenever a Digital Card Profile is - updated. - - `digital_wallet_token.created` - Occurs whenever a Digital Wallet Token is - created. - - `digital_wallet_token.updated` - Occurs whenever a Digital Wallet Token is - updated. - - `document.created` - Occurs whenever a Document is created. - - `entity.created` - Occurs whenever an Entity is created. - - `entity.updated` - Occurs whenever an Entity is updated. - - `event_subscription.created` - Occurs whenever an Event Subscription is - created. - - `event_subscription.updated` - Occurs whenever an Event Subscription is - updated. - - `export.created` - Occurs whenever an Export is created. - - `export.updated` - Occurs whenever an Export is updated. - - `external_account.created` - Occurs whenever an External Account is created. - - `external_account.updated` - Occurs whenever an External Account is updated. - - `fednow_transfer.created` - Occurs whenever a FedNow Transfer is created. - - `fednow_transfer.updated` - Occurs whenever a FedNow Transfer is updated. - - `file.created` - Occurs whenever a File is created. - - `group.updated` - Occurs whenever a Group is updated. - - `group.heartbeat` - Increase may send webhooks with this category to see if a - webhook endpoint is working properly. - - `inbound_ach_transfer.created` - Occurs whenever an Inbound ACH Transfer is - created. - - `inbound_ach_transfer.updated` - Occurs whenever an Inbound ACH Transfer is - updated. - - `inbound_ach_transfer_return.created` - Occurs whenever an Inbound ACH - Transfer Return is created. - - `inbound_ach_transfer_return.updated` - Occurs whenever an Inbound ACH - Transfer Return is updated. - - `inbound_check_deposit.created` - Occurs whenever an Inbound Check Deposit is - created. - - `inbound_check_deposit.updated` - Occurs whenever an Inbound Check Deposit is - updated. - - `inbound_fednow_transfer.created` - Occurs whenever an Inbound FedNow Transfer - is created. - - `inbound_fednow_transfer.updated` - Occurs whenever an Inbound FedNow Transfer - is updated. - - `inbound_mail_item.created` - Occurs whenever an Inbound Mail Item is created. - - `inbound_mail_item.updated` - Occurs whenever an Inbound Mail Item is updated. - - `inbound_real_time_payments_transfer.created` - Occurs whenever an Inbound - Real-Time Payments Transfer is created. - - `inbound_real_time_payments_transfer.updated` - Occurs whenever an Inbound - Real-Time Payments Transfer is updated. - - `inbound_wire_drawdown_request.created` - Occurs whenever an Inbound Wire - Drawdown Request is created. - - `inbound_wire_transfer.created` - Occurs whenever an Inbound Wire Transfer is - created. - - `inbound_wire_transfer.updated` - Occurs whenever an Inbound Wire Transfer is - updated. - - `intrafi_account_enrollment.created` - Occurs whenever an IntraFi Account - Enrollment is created. - - `intrafi_account_enrollment.updated` - Occurs whenever an IntraFi Account - Enrollment is updated. - - `intrafi_exclusion.created` - Occurs whenever an IntraFi Exclusion is created. - - `intrafi_exclusion.updated` - Occurs whenever an IntraFi Exclusion is updated. - - `legacy_card_dispute.created` - Occurs whenever a Legacy Card Dispute is - created. - - `legacy_card_dispute.updated` - Occurs whenever a Legacy Card Dispute is - updated. - - `lockbox.created` - Occurs whenever a Lockbox is created. - - `lockbox.updated` - Occurs whenever a Lockbox is updated. - - `oauth_connection.created` - Occurs whenever an OAuth Connection is created. - - `oauth_connection.deactivated` - Occurs whenever an OAuth Connection is - deactivated. - - `card_push_transfer.created` - Occurs whenever a Card Push Transfer is - created. - - `card_push_transfer.updated` - Occurs whenever a Card Push Transfer is - updated. - - `card_validation.created` - Occurs whenever a Card Validation is created. - - `card_validation.updated` - Occurs whenever a Card Validation is updated. - - `pending_transaction.created` - Occurs whenever a Pending Transaction is - created. - - `pending_transaction.updated` - Occurs whenever a Pending Transaction is - updated. - - `physical_card.created` - Occurs whenever a Physical Card is created. - - `physical_card.updated` - Occurs whenever a Physical Card is updated. - - `physical_card_profile.created` - Occurs whenever a Physical Card Profile is - created. - - `physical_card_profile.updated` - Occurs whenever a Physical Card Profile is - updated. - - `program.created` - Occurs whenever a Program is created. - - `program.updated` - Occurs whenever a Program is updated. - - `proof_of_authorization_request.created` - Occurs whenever a Proof of - Authorization Request is created. - - `proof_of_authorization_request.updated` - Occurs whenever a Proof of - Authorization Request is updated. - - `real_time_decision.card_authorization_requested` - Occurs whenever a - Real-Time Decision is created in response to a card authorization. - - `real_time_decision.card_balance_inquiry_requested` - Occurs whenever a - Real-Time Decision is created in response to a card balance inquiry. - - `real_time_decision.digital_wallet_token_requested` - Occurs whenever a - Real-Time Decision is created in response to a digital wallet provisioning - attempt. - - `real_time_decision.digital_wallet_authentication_requested` - Occurs whenever - a Real-Time Decision is created in response to a digital wallet requiring - two-factor authentication. - - `real_time_decision.card_authentication_requested` - Occurs whenever a - Real-Time Decision is created in response to 3DS authentication. - - `real_time_decision.card_authentication_challenge_requested` - Occurs whenever - a Real-Time Decision is created in response to 3DS authentication challenges. - - `real_time_payments_transfer.created` - Occurs whenever a Real-Time Payments - Transfer is created. - - `real_time_payments_transfer.updated` - Occurs whenever a Real-Time Payments - Transfer is updated. - - `real_time_payments_request_for_payment.created` - Occurs whenever a Real-Time - Payments Request for Payment is created. - - `real_time_payments_request_for_payment.updated` - Occurs whenever a Real-Time - Payments Request for Payment is updated. - - `swift_transfer.created` - Occurs whenever a Swift Transfer is created. - - `swift_transfer.updated` - Occurs whenever a Swift Transfer is updated. - - `transaction.created` - Occurs whenever a Transaction is created. - - `wire_drawdown_request.created` - Occurs whenever a Wire Drawdown Request is - created. - - `wire_drawdown_request.updated` - Occurs whenever a Wire Drawdown Request is - updated. - - `wire_transfer.created` - Occurs whenever a Wire Transfer is created. - - `wire_transfer.updated` - Occurs whenever a Wire Transfer is updated. + selected_event_categories: If specified, this subscription will only receive webhooks for Events with the + specified `category`. If specifying a Real-Time Decision event category, only + one Event Category can be specified for the Event Subscription. shared_secret: The key that will be used to sign webhooks. If no value is passed, a random string will be used as default. @@ -849,7 +336,7 @@ async def create( { "url": url, "oauth_connection_id": oauth_connection_id, - "selected_event_category": selected_event_category, + "selected_event_categories": selected_event_categories, "shared_secret": shared_secret, "status": status, }, diff --git a/src/increase/resources/events.py b/src/increase/resources/events.py index 0e6be4fbe..7638252be 100644 --- a/src/increase/resources/events.py +++ b/src/increase/resources/events.py @@ -2,12 +2,16 @@ from __future__ import annotations +import json +from typing import Mapping, cast + import httpx from ..types import event_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import maybe_transform from .._compat import cached_property +from .._models import construct_type from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( to_raw_response_wrapper, @@ -16,8 +20,10 @@ async_to_streamed_response_wrapper, ) from ..pagination import SyncPage, AsyncPage +from .._exceptions import IncreaseError from ..types.event import Event from .._base_client import AsyncPaginator, make_request_options +from ..types.unwrap_webhook_event import UnwrapWebhookEvent __all__ = ["EventsResource", "AsyncEventsResource"] @@ -133,6 +139,33 @@ def list( model=Event, ) + def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: + try: + from standardwebhooks import Webhook + except ImportError as exc: + raise IncreaseError("You need to install `increase[webhooks]` to use this method") from exc + + if key is None: + raw_key = self._client.webhook_secret + if raw_key is None: + raise ValueError( + "Cannot verify a webhook without a key on either the client's webhook_secret or passed in as an argument" + ) + key = raw_key.encode("utf-8") + + if not isinstance(headers, dict): + headers = dict(headers) + + Webhook(key).verify(payload, headers) + + return cast( + UnwrapWebhookEvent, + construct_type( + type_=UnwrapWebhookEvent, + value=json.loads(payload), + ), + ) + class AsyncEventsResource(AsyncAPIResource): @cached_property @@ -245,6 +278,33 @@ def list( model=Event, ) + def unwrap(self, payload: str, *, headers: Mapping[str, str], key: str | bytes | None = None) -> UnwrapWebhookEvent: + try: + from standardwebhooks import Webhook + except ImportError as exc: + raise IncreaseError("You need to install `increase[webhooks]` to use this method") from exc + + if key is None: + raw_key = self._client.webhook_secret + if raw_key is None: + raise ValueError( + "Cannot verify a webhook without a key on either the client's webhook_secret or passed in as an argument" + ) + key = raw_key.encode("utf-8") + + if not isinstance(headers, dict): + headers = dict(headers) + + Webhook(key).verify(payload, headers) + + return cast( + UnwrapWebhookEvent, + construct_type( + type_=UnwrapWebhookEvent, + value=json.loads(payload), + ), + ) + class EventsResourceWithRawResponse: def __init__(self, events: EventsResource) -> None: diff --git a/src/increase/resources/exports.py b/src/increase/resources/exports.py index f58378da1..f71932ac2 100644 --- a/src/increase/resources/exports.py +++ b/src/increase/resources/exports.py @@ -57,6 +57,7 @@ def create( "vendor_csv", "account_verification_letter", "funding_instructions", + "voided_check", ], account_statement_bai2: export_create_params.AccountStatementBai2 | Omit = omit, account_statement_ofx: export_create_params.AccountStatementOfx | Omit = omit, @@ -67,6 +68,7 @@ def create( funding_instructions: export_create_params.FundingInstructions | Omit = omit, transaction_csv: export_create_params.TransactionCsv | Omit = omit, vendor_csv: export_create_params.VendorCsv | Omit = omit, + voided_check: export_create_params.VoidedCheck | 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, @@ -95,6 +97,7 @@ def create( management dashboard. - `account_verification_letter` - A PDF of an account verification letter. - `funding_instructions` - A PDF of funding instructions. + - `voided_check` - A PDF of a voided check. account_statement_bai2: Options for the created export. Required if `category` is equal to `account_statement_bai2`. @@ -121,6 +124,9 @@ def create( vendor_csv: Options for the created export. Required if `category` is equal to `vendor_csv`. + voided_check: Options for the created export. Required if `category` is equal to + `voided_check`. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -145,6 +151,7 @@ def create( "funding_instructions": funding_instructions, "transaction_csv": transaction_csv, "vendor_csv": vendor_csv, + "voided_check": voided_check, }, export_create_params.ExportCreateParams, ), @@ -196,9 +203,27 @@ def retrieve( def list( self, *, - category: export_list_params.Category | Omit = omit, + category: Literal[ + "account_statement_ofx", + "account_statement_bai2", + "transaction_csv", + "balance_csv", + "bookkeeping_account_balance_csv", + "entity_csv", + "vendor_csv", + "dashboard_table_csv", + "account_verification_letter", + "funding_instructions", + "form_1099_int", + "form_1099_misc", + "fee_csv", + "voided_check", + ] + | Omit = omit, created_at: export_list_params.CreatedAt | Omit = omit, cursor: str | Omit = omit, + form_1099_int: export_list_params.Form1099Int | Omit = omit, + form_1099_misc: export_list_params.Form1099Misc | Omit = omit, idempotency_key: str | Omit = omit, limit: int | Omit = omit, status: export_list_params.Status | Omit = omit, @@ -213,6 +238,30 @@ def list( List Exports Args: + category: Filter Exports for those with the specified category. + + - `account_statement_ofx` - Export an Open Financial Exchange (OFX) file of + transactions and balances for a given time range and Account. + - `account_statement_bai2` - Export a BAI2 file of transactions and balances for + a given date and optional Account. + - `transaction_csv` - Export a CSV of all transactions for a given time range. + - `balance_csv` - Export a CSV of account balances for the dates in a given + range. + - `bookkeeping_account_balance_csv` - Export a CSV of bookkeeping account + balances for the dates in a given range. + - `entity_csv` - Export a CSV of entities with a given status. + - `vendor_csv` - Export a CSV of vendors added to the third-party risk + management dashboard. + - `dashboard_table_csv` - Certain dashboard tables are available as CSV exports. + This export cannot be created via the API. + - `account_verification_letter` - A PDF of an account verification letter. + - `funding_instructions` - A PDF of funding instructions. + - `form_1099_int` - A PDF of an Internal Revenue Service Form 1099-INT. + - `form_1099_misc` - A PDF of an Internal Revenue Service Form 1099-MISC. + - `fee_csv` - Export a CSV of fees. The time range must not include any fees + that are part of an open fee statement. + - `voided_check` - A PDF of a voided check. + cursor: Return the page of entries after this one. idempotency_key: Filter records to the one with the specified `idempotency_key` you chose for @@ -244,6 +293,8 @@ def list( "category": category, "created_at": created_at, "cursor": cursor, + "form_1099_int": form_1099_int, + "form_1099_misc": form_1099_misc, "idempotency_key": idempotency_key, "limit": limit, "status": status, @@ -288,6 +339,7 @@ async def create( "vendor_csv", "account_verification_letter", "funding_instructions", + "voided_check", ], account_statement_bai2: export_create_params.AccountStatementBai2 | Omit = omit, account_statement_ofx: export_create_params.AccountStatementOfx | Omit = omit, @@ -298,6 +350,7 @@ async def create( funding_instructions: export_create_params.FundingInstructions | Omit = omit, transaction_csv: export_create_params.TransactionCsv | Omit = omit, vendor_csv: export_create_params.VendorCsv | Omit = omit, + voided_check: export_create_params.VoidedCheck | 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, @@ -326,6 +379,7 @@ async def create( management dashboard. - `account_verification_letter` - A PDF of an account verification letter. - `funding_instructions` - A PDF of funding instructions. + - `voided_check` - A PDF of a voided check. account_statement_bai2: Options for the created export. Required if `category` is equal to `account_statement_bai2`. @@ -352,6 +406,9 @@ async def create( vendor_csv: Options for the created export. Required if `category` is equal to `vendor_csv`. + voided_check: Options for the created export. Required if `category` is equal to + `voided_check`. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -376,6 +433,7 @@ async def create( "funding_instructions": funding_instructions, "transaction_csv": transaction_csv, "vendor_csv": vendor_csv, + "voided_check": voided_check, }, export_create_params.ExportCreateParams, ), @@ -427,9 +485,27 @@ async def retrieve( def list( self, *, - category: export_list_params.Category | Omit = omit, + category: Literal[ + "account_statement_ofx", + "account_statement_bai2", + "transaction_csv", + "balance_csv", + "bookkeeping_account_balance_csv", + "entity_csv", + "vendor_csv", + "dashboard_table_csv", + "account_verification_letter", + "funding_instructions", + "form_1099_int", + "form_1099_misc", + "fee_csv", + "voided_check", + ] + | Omit = omit, created_at: export_list_params.CreatedAt | Omit = omit, cursor: str | Omit = omit, + form_1099_int: export_list_params.Form1099Int | Omit = omit, + form_1099_misc: export_list_params.Form1099Misc | Omit = omit, idempotency_key: str | Omit = omit, limit: int | Omit = omit, status: export_list_params.Status | Omit = omit, @@ -444,6 +520,30 @@ def list( List Exports Args: + category: Filter Exports for those with the specified category. + + - `account_statement_ofx` - Export an Open Financial Exchange (OFX) file of + transactions and balances for a given time range and Account. + - `account_statement_bai2` - Export a BAI2 file of transactions and balances for + a given date and optional Account. + - `transaction_csv` - Export a CSV of all transactions for a given time range. + - `balance_csv` - Export a CSV of account balances for the dates in a given + range. + - `bookkeeping_account_balance_csv` - Export a CSV of bookkeeping account + balances for the dates in a given range. + - `entity_csv` - Export a CSV of entities with a given status. + - `vendor_csv` - Export a CSV of vendors added to the third-party risk + management dashboard. + - `dashboard_table_csv` - Certain dashboard tables are available as CSV exports. + This export cannot be created via the API. + - `account_verification_letter` - A PDF of an account verification letter. + - `funding_instructions` - A PDF of funding instructions. + - `form_1099_int` - A PDF of an Internal Revenue Service Form 1099-INT. + - `form_1099_misc` - A PDF of an Internal Revenue Service Form 1099-MISC. + - `fee_csv` - Export a CSV of fees. The time range must not include any fees + that are part of an open fee statement. + - `voided_check` - A PDF of a voided check. + cursor: Return the page of entries after this one. idempotency_key: Filter records to the one with the specified `idempotency_key` you chose for @@ -475,6 +575,8 @@ def list( "category": category, "created_at": created_at, "cursor": cursor, + "form_1099_int": form_1099_int, + "form_1099_misc": form_1099_misc, "idempotency_key": idempotency_key, "limit": limit, "status": status, diff --git a/src/increase/resources/file_links.py b/src/increase/resources/file_links.py index cb8a8f9e0..f31574997 100644 --- a/src/increase/resources/file_links.py +++ b/src/increase/resources/file_links.py @@ -64,7 +64,7 @@ def create( file_id: The File to create a File Link for. expires_at: The time at which the File Link will expire. The default is 1 hour from the time - of the request. The maxiumum is 1 day from the time of the request. + of the request. The maximum is 1 day from the time of the request. extra_headers: Send extra headers @@ -136,7 +136,7 @@ async def create( file_id: The File to create a File Link for. expires_at: The time at which the File Link will expire. The default is 1 hour from the time - of the request. The maxiumum is 1 day from the time of the request. + of the request. The maximum is 1 day from the time of the request. extra_headers: Send extra headers diff --git a/src/increase/resources/inbound_check_deposits.py b/src/increase/resources/inbound_check_deposits.py index 4337bcd62..0a924f241 100644 --- a/src/increase/resources/inbound_check_deposits.py +++ b/src/increase/resources/inbound_check_deposits.py @@ -194,6 +194,7 @@ def return_( "duplicate_presentment", "endorsement_missing", "endorsement_irregular", + "refer_to_maker", ], # 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. @@ -216,6 +217,7 @@ def return_( - `duplicate_presentment` - The check was a duplicate presentment. - `endorsement_missing` - The check was not endorsed. - `endorsement_irregular` - The check was not endorsed by the payee. + - `refer_to_maker` - The maker of the check requested its return. extra_headers: Send extra headers @@ -417,6 +419,7 @@ async def return_( "duplicate_presentment", "endorsement_missing", "endorsement_irregular", + "refer_to_maker", ], # 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. @@ -439,6 +442,7 @@ async def return_( - `duplicate_presentment` - The check was a duplicate presentment. - `endorsement_missing` - The check was not endorsed. - `endorsement_irregular` - The check was not endorsed by the payee. + - `refer_to_maker` - The maker of the check requested its return. extra_headers: Send extra headers diff --git a/src/increase/resources/inbound_mail_items.py b/src/increase/resources/inbound_mail_items.py index 7e04c7944..b4b95197a 100644 --- a/src/increase/resources/inbound_mail_items.py +++ b/src/increase/resources/inbound_mail_items.py @@ -149,7 +149,7 @@ def action( idempotency_key: str | None = None, ) -> InboundMailItem: """ - Action a Inbound Mail Item + Action an Inbound Mail Item Args: inbound_mail_item_id: The identifier of the Inbound Mail Item to action. @@ -309,7 +309,7 @@ async def action( idempotency_key: str | None = None, ) -> InboundMailItem: """ - Action a Inbound Mail Item + Action an Inbound Mail Item Args: inbound_mail_item_id: The identifier of the Inbound Mail Item to action. diff --git a/src/increase/resources/intrafi_exclusions.py b/src/increase/resources/intrafi_exclusions.py index 53e2563c4..344323023 100644 --- a/src/increase/resources/intrafi_exclusions.py +++ b/src/increase/resources/intrafi_exclusions.py @@ -45,8 +45,8 @@ def with_streaming_response(self) -> IntrafiExclusionsResourceWithStreamingRespo def create( self, *, - bank_name: str, entity_id: str, + fdic_certificate_number: str, # 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, @@ -59,10 +59,13 @@ def create( Create an IntraFi Exclusion Args: - bank_name: The name of the financial institution to be excluded. - entity_id: The identifier of the Entity whose deposits will be excluded. + fdic_certificate_number: The FDIC certificate number of the financial institution to be excluded. An FDIC + certificate number uniquely identifies a financial institution, and is different + than a routing number. To find one, we recommend searching by Bank Name using + the [FDIC's bankfind tool](https://banks.data.fdic.gov/bankfind-suite/bankfind). + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -77,8 +80,8 @@ def create( "/intrafi_exclusions", body=maybe_transform( { - "bank_name": bank_name, "entity_id": entity_id, + "fdic_certificate_number": fdic_certificate_number, }, intrafi_exclusion_create_params.IntrafiExclusionCreateParams, ), @@ -258,8 +261,8 @@ def with_streaming_response(self) -> AsyncIntrafiExclusionsResourceWithStreaming async def create( self, *, - bank_name: str, entity_id: str, + fdic_certificate_number: str, # 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, @@ -272,10 +275,13 @@ async def create( Create an IntraFi Exclusion Args: - bank_name: The name of the financial institution to be excluded. - entity_id: The identifier of the Entity whose deposits will be excluded. + fdic_certificate_number: The FDIC certificate number of the financial institution to be excluded. An FDIC + certificate number uniquely identifies a financial institution, and is different + than a routing number. To find one, we recommend searching by Bank Name using + the [FDIC's bankfind tool](https://banks.data.fdic.gov/bankfind-suite/bankfind). + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -290,8 +296,8 @@ async def create( "/intrafi_exclusions", body=await async_maybe_transform( { - "bank_name": bank_name, "entity_id": entity_id, + "fdic_certificate_number": fdic_certificate_number, }, intrafi_exclusion_create_params.IntrafiExclusionCreateParams, ), diff --git a/src/increase/resources/simulations/__init__.py b/src/increase/resources/simulations/__init__.py index 93e0e270f..972e5b7bd 100644 --- a/src/increase/resources/simulations/__init__.py +++ b/src/increase/resources/simulations/__init__.py @@ -152,6 +152,14 @@ CardAuthorizationsResourceWithStreamingResponse, AsyncCardAuthorizationsResourceWithStreamingResponse, ) +from .card_authentications import ( + CardAuthenticationsResource, + AsyncCardAuthenticationsResource, + CardAuthenticationsResourceWithRawResponse, + AsyncCardAuthenticationsResourceWithRawResponse, + CardAuthenticationsResourceWithStreamingResponse, + AsyncCardAuthenticationsResourceWithStreamingResponse, +) from .pending_transactions import ( PendingTransactionsResource, AsyncPendingTransactionsResource, @@ -318,6 +326,12 @@ "AsyncCardRefundsResourceWithRawResponse", "CardRefundsResourceWithStreamingResponse", "AsyncCardRefundsResourceWithStreamingResponse", + "CardAuthenticationsResource", + "AsyncCardAuthenticationsResource", + "CardAuthenticationsResourceWithRawResponse", + "AsyncCardAuthenticationsResourceWithRawResponse", + "CardAuthenticationsResourceWithStreamingResponse", + "AsyncCardAuthenticationsResourceWithStreamingResponse", "CardDisputesResource", "AsyncCardDisputesResource", "CardDisputesResourceWithRawResponse", diff --git a/src/increase/resources/simulations/ach_transfers.py b/src/increase/resources/simulations/ach_transfers.py index b224645f3..2eda2f5cd 100644 --- a/src/increase/resources/simulations/ach_transfers.py +++ b/src/increase/resources/simulations/ach_transfers.py @@ -61,10 +61,10 @@ def acknowledge( ) -> ACHTransfer: """ Simulates the acknowledgement of an [ACH Transfer](#ach-transfers) by the - Federal Reserve. This transfer must first have a `status` of `submitted` . In + Federal Reserve. This transfer must first have a `status` of `submitted`. In production, the Federal Reserve generally acknowledges submitted ACH files within 30 minutes. Since sandbox ACH Transfers are not submitted to the Federal - Reserve, this endpoint allows you to skip that delay and add the acknowledgment + Reserve, this endpoint allows you to skip that delay and add the acknowledgement subresource to the ACH Transfer. Args: @@ -303,24 +303,28 @@ def return_( Defaults to `no_account`. - `insufficient_fund` - Code R01. Insufficient funds in the receiving account. - Sometimes abbreviated to NSF. + Sometimes abbreviated to "NSF." - `no_account` - Code R03. The account does not exist or the receiving bank was unable to locate it. - `account_closed` - Code R02. The account is closed at the receiving bank. - `invalid_account_number_structure` - Code R04. The account number is invalid at the receiving bank. - - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. The account - at the receiving bank was frozen per the Office of Foreign Assets Control. - - `credit_entry_refused_by_receiver` - Code R23. The receiving bank account - refused a credit transfer. + - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. This return + code has two separate meanings. (1) The receiving bank froze the account or + (2) the Office of Foreign Assets Control (OFAC) instructed the receiving bank + to return the entry. + - `credit_entry_refused_by_receiver` - Code R23. The receiving bank refused the + credit transfer. - `unauthorized_debit_to_consumer_account_using_corporate_sec_code` - Code R05. The receiving bank rejected because of an incorrect Standard Entry Class code. + Consumer accounts cannot be debited as `corporate_credit_or_debit` or + `corporate_trade_exchange`. - `corporate_customer_advised_not_authorized` - Code R29. The corporate customer at the receiving bank reversed the transfer. - `payment_stopped` - Code R08. The receiving bank stopped payment on this transfer. - - `non_transaction_account` - Code R20. The receiving bank account does not - perform transfers. + - `non_transaction_account` - Code R20. The account is not eligible for ACH, + such as a savings account with transaction limits. - `uncollected_funds` - Code R09. The receiving bank account does not have enough available balance for the transfer. - `routing_number_check_digit_error` - Code R28. The routing number is @@ -328,14 +332,13 @@ def return_( - `customer_advised_unauthorized_improper_ineligible_or_incomplete` - Code R10. The customer at the receiving bank reversed the transfer. - `amount_field_error` - Code R19. The amount field is incorrect or too large. - - `authorization_revoked_by_customer` - Code R07. The customer at the receiving - institution informed their bank that they have revoked authorization for a - previously authorized transfer. + - `authorization_revoked_by_customer` - Code R07. The customer revoked their + authorization for a previously authorized transfer. - `invalid_ach_routing_number` - Code R13. The routing number is invalid. - `file_record_edit_criteria` - Code R17. The receiving bank is unable to process a field in the transfer. - - `enr_invalid_individual_name` - Code R45. The individual name field was - invalid. + - `enr_invalid_individual_name` - Code R45. A rare return reason. The individual + name field was invalid. - `returned_per_odfi_request` - Code R06. The originating financial institution asked for this transfer to be returned. The receiving bank is complying with the request. @@ -430,8 +433,8 @@ def return_( a malformed credit entry. - `return_of_improper_debit_entry` - Code R35. A rare return reason. Return of a malformed debit entry. - - `return_of_xck_entry` - Code R33. A rare return reason. Return of a Destroyed - Check ("XKC") entry. + - `return_of_xck_entry` - Code R33. A rare return reason. Return of a destroyed + check ("XCK") entry. - `source_document_presented_for_payment` - Code R37. A rare return reason. The source document related to this ACH, usually an ACH check conversion, was presented to the bank. @@ -620,10 +623,10 @@ async def acknowledge( ) -> ACHTransfer: """ Simulates the acknowledgement of an [ACH Transfer](#ach-transfers) by the - Federal Reserve. This transfer must first have a `status` of `submitted` . In + Federal Reserve. This transfer must first have a `status` of `submitted`. In production, the Federal Reserve generally acknowledges submitted ACH files within 30 minutes. Since sandbox ACH Transfers are not submitted to the Federal - Reserve, this endpoint allows you to skip that delay and add the acknowledgment + Reserve, this endpoint allows you to skip that delay and add the acknowledgement subresource to the ACH Transfer. Args: @@ -862,24 +865,28 @@ async def return_( Defaults to `no_account`. - `insufficient_fund` - Code R01. Insufficient funds in the receiving account. - Sometimes abbreviated to NSF. + Sometimes abbreviated to "NSF." - `no_account` - Code R03. The account does not exist or the receiving bank was unable to locate it. - `account_closed` - Code R02. The account is closed at the receiving bank. - `invalid_account_number_structure` - Code R04. The account number is invalid at the receiving bank. - - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. The account - at the receiving bank was frozen per the Office of Foreign Assets Control. - - `credit_entry_refused_by_receiver` - Code R23. The receiving bank account - refused a credit transfer. + - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. This return + code has two separate meanings. (1) The receiving bank froze the account or + (2) the Office of Foreign Assets Control (OFAC) instructed the receiving bank + to return the entry. + - `credit_entry_refused_by_receiver` - Code R23. The receiving bank refused the + credit transfer. - `unauthorized_debit_to_consumer_account_using_corporate_sec_code` - Code R05. The receiving bank rejected because of an incorrect Standard Entry Class code. + Consumer accounts cannot be debited as `corporate_credit_or_debit` or + `corporate_trade_exchange`. - `corporate_customer_advised_not_authorized` - Code R29. The corporate customer at the receiving bank reversed the transfer. - `payment_stopped` - Code R08. The receiving bank stopped payment on this transfer. - - `non_transaction_account` - Code R20. The receiving bank account does not - perform transfers. + - `non_transaction_account` - Code R20. The account is not eligible for ACH, + such as a savings account with transaction limits. - `uncollected_funds` - Code R09. The receiving bank account does not have enough available balance for the transfer. - `routing_number_check_digit_error` - Code R28. The routing number is @@ -887,14 +894,13 @@ async def return_( - `customer_advised_unauthorized_improper_ineligible_or_incomplete` - Code R10. The customer at the receiving bank reversed the transfer. - `amount_field_error` - Code R19. The amount field is incorrect or too large. - - `authorization_revoked_by_customer` - Code R07. The customer at the receiving - institution informed their bank that they have revoked authorization for a - previously authorized transfer. + - `authorization_revoked_by_customer` - Code R07. The customer revoked their + authorization for a previously authorized transfer. - `invalid_ach_routing_number` - Code R13. The routing number is invalid. - `file_record_edit_criteria` - Code R17. The receiving bank is unable to process a field in the transfer. - - `enr_invalid_individual_name` - Code R45. The individual name field was - invalid. + - `enr_invalid_individual_name` - Code R45. A rare return reason. The individual + name field was invalid. - `returned_per_odfi_request` - Code R06. The originating financial institution asked for this transfer to be returned. The receiving bank is complying with the request. @@ -989,8 +995,8 @@ async def return_( a malformed credit entry. - `return_of_improper_debit_entry` - Code R35. A rare return reason. Return of a malformed debit entry. - - `return_of_xck_entry` - Code R33. A rare return reason. Return of a Destroyed - Check ("XKC") entry. + - `return_of_xck_entry` - Code R33. A rare return reason. Return of a destroyed + check ("XCK") entry. - `source_document_presented_for_payment` - Code R37. A rare return reason. The source document related to this ACH, usually an ACH check conversion, was presented to the bank. diff --git a/src/increase/resources/simulations/card_authentications.py b/src/increase/resources/simulations/card_authentications.py new file mode 100644 index 000000000..432a9b574 --- /dev/null +++ b/src/increase/resources/simulations/card_authentications.py @@ -0,0 +1,501 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.simulations import card_authentication_create_params, card_authentication_challenge_attempts_params +from ...types.card_payment import CardPayment + +__all__ = ["CardAuthenticationsResource", "AsyncCardAuthenticationsResource"] + + +class CardAuthenticationsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> CardAuthenticationsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/Increase/increase-python#accessing-raw-response-data-eg-headers + """ + return CardAuthenticationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CardAuthenticationsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Increase/increase-python#with_streaming_response + """ + return CardAuthenticationsResourceWithStreamingResponse(self) + + def create( + self, + *, + card_id: str, + category: Literal["payment_authentication", "non_payment_authentication"] | Omit = omit, + device_channel: Literal["app", "browser", "three_ds_requestor_initiated"] | Omit = omit, + merchant_acceptor_id: str | Omit = omit, + merchant_category_code: str | Omit = omit, + merchant_country: str | Omit = omit, + merchant_name: str | Omit = omit, + purchase_amount: int | 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, + idempotency_key: str | None = None, + ) -> CardPayment: + """Simulates a Card Authentication attempt on a [Card](#cards). + + The attempt always + results in a [Card Payment](#card_payments) being created, either with a status + that allows further action or a terminal failed status. + + Args: + card_id: The identifier of the Card to be authorized. + + category: The category of the card authentication attempt. + + - `payment_authentication` - The authentication attempt is for a payment. + - `non_payment_authentication` - The authentication attempt is not for a + payment. + + device_channel: The device channel of the card authentication attempt. + + - `app` - The authentication attempt was made from an app. + - `browser` - The authentication attempt was made from a browser. + - `three_ds_requestor_initiated` - The authentication attempt was initiated by + the 3DS Requestor. + + merchant_acceptor_id: The merchant identifier (commonly abbreviated as MID) of the merchant the card + is transacting with. + + merchant_category_code: The Merchant Category Code (commonly abbreviated as MCC) of the merchant the + card is transacting with. + + merchant_country: The country the merchant resides in. + + merchant_name: The name of the merchant + + purchase_amount: The purchase amount in cents. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return self._post( + "/simulations/card_authentications", + body=maybe_transform( + { + "card_id": card_id, + "category": category, + "device_channel": device_channel, + "merchant_acceptor_id": merchant_acceptor_id, + "merchant_category_code": merchant_category_code, + "merchant_country": merchant_country, + "merchant_name": merchant_name, + "purchase_amount": purchase_amount, + }, + card_authentication_create_params.CardAuthenticationCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CardPayment, + ) + + def challenge_attempts( + self, + card_payment_id: str, + *, + one_time_code: str, + # 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, + idempotency_key: str | None = None, + ) -> CardPayment: + """Simulates an attempt at a Card Authentication Challenge. + + This updates the + `card_authentications` object under the [Card Payment](#card_payments). You can + also attempt the challenge by navigating to + https://dashboard.increase.com/card_authentication_simulation/:card_payment_id. + + Args: + card_payment_id: The identifier of the Card Payment to be challenged. + + one_time_code: The one-time code to be validated. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not card_payment_id: + raise ValueError(f"Expected a non-empty value for `card_payment_id` but received {card_payment_id!r}") + return self._post( + f"/simulations/card_authentications/{card_payment_id}/challenge_attempts", + body=maybe_transform( + {"one_time_code": one_time_code}, + card_authentication_challenge_attempts_params.CardAuthenticationChallengeAttemptsParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CardPayment, + ) + + def challenges( + self, + card_payment_id: str, + *, + # 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, + idempotency_key: str | None = None, + ) -> CardPayment: + """ + Simulates starting a Card Authentication Challenge for an existing Card + Authentication. This updates the `card_authentications` object under the + [Card Payment](#card_payments). To attempt the challenge, use the + `/simulations/card_authentications/:card_payment_id/challenge_attempts` endpoint + or navigate to + https://dashboard.increase.com/card_authentication_simulation/:card_payment_id. + + Args: + card_payment_id: The identifier of the Card Payment to be challenged. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not card_payment_id: + raise ValueError(f"Expected a non-empty value for `card_payment_id` but received {card_payment_id!r}") + return self._post( + f"/simulations/card_authentications/{card_payment_id}/challenges", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CardPayment, + ) + + +class AsyncCardAuthenticationsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncCardAuthenticationsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/Increase/increase-python#accessing-raw-response-data-eg-headers + """ + return AsyncCardAuthenticationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCardAuthenticationsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Increase/increase-python#with_streaming_response + """ + return AsyncCardAuthenticationsResourceWithStreamingResponse(self) + + async def create( + self, + *, + card_id: str, + category: Literal["payment_authentication", "non_payment_authentication"] | Omit = omit, + device_channel: Literal["app", "browser", "three_ds_requestor_initiated"] | Omit = omit, + merchant_acceptor_id: str | Omit = omit, + merchant_category_code: str | Omit = omit, + merchant_country: str | Omit = omit, + merchant_name: str | Omit = omit, + purchase_amount: int | 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, + idempotency_key: str | None = None, + ) -> CardPayment: + """Simulates a Card Authentication attempt on a [Card](#cards). + + The attempt always + results in a [Card Payment](#card_payments) being created, either with a status + that allows further action or a terminal failed status. + + Args: + card_id: The identifier of the Card to be authorized. + + category: The category of the card authentication attempt. + + - `payment_authentication` - The authentication attempt is for a payment. + - `non_payment_authentication` - The authentication attempt is not for a + payment. + + device_channel: The device channel of the card authentication attempt. + + - `app` - The authentication attempt was made from an app. + - `browser` - The authentication attempt was made from a browser. + - `three_ds_requestor_initiated` - The authentication attempt was initiated by + the 3DS Requestor. + + merchant_acceptor_id: The merchant identifier (commonly abbreviated as MID) of the merchant the card + is transacting with. + + merchant_category_code: The Merchant Category Code (commonly abbreviated as MCC) of the merchant the + card is transacting with. + + merchant_country: The country the merchant resides in. + + merchant_name: The name of the merchant + + purchase_amount: The purchase amount in cents. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return await self._post( + "/simulations/card_authentications", + body=await async_maybe_transform( + { + "card_id": card_id, + "category": category, + "device_channel": device_channel, + "merchant_acceptor_id": merchant_acceptor_id, + "merchant_category_code": merchant_category_code, + "merchant_country": merchant_country, + "merchant_name": merchant_name, + "purchase_amount": purchase_amount, + }, + card_authentication_create_params.CardAuthenticationCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CardPayment, + ) + + async def challenge_attempts( + self, + card_payment_id: str, + *, + one_time_code: str, + # 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, + idempotency_key: str | None = None, + ) -> CardPayment: + """Simulates an attempt at a Card Authentication Challenge. + + This updates the + `card_authentications` object under the [Card Payment](#card_payments). You can + also attempt the challenge by navigating to + https://dashboard.increase.com/card_authentication_simulation/:card_payment_id. + + Args: + card_payment_id: The identifier of the Card Payment to be challenged. + + one_time_code: The one-time code to be validated. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not card_payment_id: + raise ValueError(f"Expected a non-empty value for `card_payment_id` but received {card_payment_id!r}") + return await self._post( + f"/simulations/card_authentications/{card_payment_id}/challenge_attempts", + body=await async_maybe_transform( + {"one_time_code": one_time_code}, + card_authentication_challenge_attempts_params.CardAuthenticationChallengeAttemptsParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CardPayment, + ) + + async def challenges( + self, + card_payment_id: str, + *, + # 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, + idempotency_key: str | None = None, + ) -> CardPayment: + """ + Simulates starting a Card Authentication Challenge for an existing Card + Authentication. This updates the `card_authentications` object under the + [Card Payment](#card_payments). To attempt the challenge, use the + `/simulations/card_authentications/:card_payment_id/challenge_attempts` endpoint + or navigate to + https://dashboard.increase.com/card_authentication_simulation/:card_payment_id. + + Args: + card_payment_id: The identifier of the Card Payment to be challenged. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not card_payment_id: + raise ValueError(f"Expected a non-empty value for `card_payment_id` but received {card_payment_id!r}") + return await self._post( + f"/simulations/card_authentications/{card_payment_id}/challenges", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CardPayment, + ) + + +class CardAuthenticationsResourceWithRawResponse: + def __init__(self, card_authentications: CardAuthenticationsResource) -> None: + self._card_authentications = card_authentications + + self.create = to_raw_response_wrapper( + card_authentications.create, + ) + self.challenge_attempts = to_raw_response_wrapper( + card_authentications.challenge_attempts, + ) + self.challenges = to_raw_response_wrapper( + card_authentications.challenges, + ) + + +class AsyncCardAuthenticationsResourceWithRawResponse: + def __init__(self, card_authentications: AsyncCardAuthenticationsResource) -> None: + self._card_authentications = card_authentications + + self.create = async_to_raw_response_wrapper( + card_authentications.create, + ) + self.challenge_attempts = async_to_raw_response_wrapper( + card_authentications.challenge_attempts, + ) + self.challenges = async_to_raw_response_wrapper( + card_authentications.challenges, + ) + + +class CardAuthenticationsResourceWithStreamingResponse: + def __init__(self, card_authentications: CardAuthenticationsResource) -> None: + self._card_authentications = card_authentications + + self.create = to_streamed_response_wrapper( + card_authentications.create, + ) + self.challenge_attempts = to_streamed_response_wrapper( + card_authentications.challenge_attempts, + ) + self.challenges = to_streamed_response_wrapper( + card_authentications.challenges, + ) + + +class AsyncCardAuthenticationsResourceWithStreamingResponse: + def __init__(self, card_authentications: AsyncCardAuthenticationsResource) -> None: + self._card_authentications = card_authentications + + self.create = async_to_streamed_response_wrapper( + card_authentications.create, + ) + self.challenge_attempts = async_to_streamed_response_wrapper( + card_authentications.challenge_attempts, + ) + self.challenges = async_to_streamed_response_wrapper( + card_authentications.challenges, + ) diff --git a/src/increase/resources/simulations/card_authorizations.py b/src/increase/resources/simulations/card_authorizations.py index c570372c4..6c281fdeb 100644 --- a/src/increase/resources/simulations/card_authorizations.py +++ b/src/increase/resources/simulations/card_authorizations.py @@ -67,6 +67,7 @@ def create( "declined_by_stand_in_processing", "invalid_physical_card", "missing_original_authorization", + "invalid_cryptogram", "failed_3ds_authentication", "suspected_card_testing", "suspected_fraud", @@ -133,10 +134,12 @@ def create( - `webhook_timed_out` - Your application webhook did not respond without the required timeout. - `declined_by_stand_in_processing` - Declined by stand-in processing. - - `invalid_physical_card` - The card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The card read had an invalid CVV or dCVV. - `missing_original_authorization` - The original card authorization for this incremental authorization does not exist. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `failed_3ds_authentication` - The transaction was declined because the 3DS authentication failed. - `suspected_card_testing` - The transaction was suspected to be used by a card @@ -267,6 +270,7 @@ async def create( "declined_by_stand_in_processing", "invalid_physical_card", "missing_original_authorization", + "invalid_cryptogram", "failed_3ds_authentication", "suspected_card_testing", "suspected_fraud", @@ -333,10 +337,12 @@ async def create( - `webhook_timed_out` - Your application webhook did not respond without the required timeout. - `declined_by_stand_in_processing` - Declined by stand-in processing. - - `invalid_physical_card` - The card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The card read had an invalid CVV or dCVV. - `missing_original_authorization` - The original card authorization for this incremental authorization does not exist. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `failed_3ds_authentication` - The transaction was declined because the 3DS authentication failed. - `suspected_card_testing` - The transaction was suspected to be used by a card diff --git a/src/increase/resources/simulations/card_balance_inquiries.py b/src/increase/resources/simulations/card_balance_inquiries.py index adfd37367..a7541cb66 100644 --- a/src/increase/resources/simulations/card_balance_inquiries.py +++ b/src/increase/resources/simulations/card_balance_inquiries.py @@ -66,6 +66,7 @@ def create( "declined_by_stand_in_processing", "invalid_physical_card", "missing_original_authorization", + "invalid_cryptogram", "failed_3ds_authentication", "suspected_card_testing", "suspected_fraud", @@ -121,10 +122,12 @@ def create( - `webhook_timed_out` - Your application webhook did not respond without the required timeout. - `declined_by_stand_in_processing` - Declined by stand-in processing. - - `invalid_physical_card` - The card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The card read had an invalid CVV or dCVV. - `missing_original_authorization` - The original card authorization for this incremental authorization does not exist. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `failed_3ds_authentication` - The transaction was declined because the 3DS authentication failed. - `suspected_card_testing` - The transaction was suspected to be used by a card @@ -249,6 +252,7 @@ async def create( "declined_by_stand_in_processing", "invalid_physical_card", "missing_original_authorization", + "invalid_cryptogram", "failed_3ds_authentication", "suspected_card_testing", "suspected_fraud", @@ -304,10 +308,12 @@ async def create( - `webhook_timed_out` - Your application webhook did not respond without the required timeout. - `declined_by_stand_in_processing` - Declined by stand-in processing. - - `invalid_physical_card` - The card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The card read had an invalid CVV or dCVV. - `missing_original_authorization` - The original card authorization for this incremental authorization does not exist. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `failed_3ds_authentication` - The transaction was declined because the 3DS authentication failed. - `suspected_card_testing` - The transaction was suspected to be used by a card diff --git a/src/increase/resources/simulations/card_increments.py b/src/increase/resources/simulations/card_increments.py index 43b0f87b7..b89372e8c 100644 --- a/src/increase/resources/simulations/card_increments.py +++ b/src/increase/resources/simulations/card_increments.py @@ -63,7 +63,7 @@ def create( Args: amount: The amount of the increment in minor units in the card authorization's currency. - card_payment_id: The identifier of the Card Payment to create a increment on. + card_payment_id: The identifier of the Card Payment to create an increment on. event_subscription_id: The identifier of the Event Subscription to use. If provided, will override the default real time event subscription. Because you can only create one real time @@ -143,7 +143,7 @@ async def create( Args: amount: The amount of the increment in minor units in the card authorization's currency. - card_payment_id: The identifier of the Card Payment to create a increment on. + card_payment_id: The identifier of the Card Payment to create an increment on. event_subscription_id: The identifier of the Event Subscription to use. If provided, will override the default real time event subscription. Because you can only create one real time diff --git a/src/increase/resources/simulations/check_deposits.py b/src/increase/resources/simulations/check_deposits.py index ba4448fb8..1fa37c646 100644 --- a/src/increase/resources/simulations/check_deposits.py +++ b/src/increase/resources/simulations/check_deposits.py @@ -2,9 +2,12 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx -from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -14,6 +17,7 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options +from ...types.simulations import check_deposit_submit_params, check_deposit_adjustment_params from ...types.check_deposit import CheckDeposit __all__ = ["CheckDepositsResource", "AsyncCheckDepositsResource"] @@ -39,6 +43,80 @@ def with_streaming_response(self) -> CheckDepositsResourceWithStreamingResponse: """ return CheckDepositsResourceWithStreamingResponse(self) + def adjustment( + self, + check_deposit_id: str, + *, + amount: int | Omit = omit, + reason: Literal["late_return", "wrong_payee_credit", "adjusted_amount", "non_conforming_item", "paid"] + | 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, + idempotency_key: str | None = None, + ) -> CheckDeposit: + """ + Simulates the creation of a + [Check Deposit Adjustment](#check-deposit-adjustments) on a + [Check Deposit](#check-deposits). This Check Deposit must first have a `status` + of `submitted`. + + Args: + check_deposit_id: The identifier of the Check Deposit you wish to adjust. + + amount: The adjustment amount in the minor unit of the Check Deposit's currency (e.g., + cents). A negative amount means that the funds are being clawed back by the + other bank and is a debit to your account. Defaults to the negative of the Check + Deposit amount. + + reason: The reason for the adjustment. Defaults to `non_conforming_item`, which is often + used for a low quality image that the recipient wasn't able to handle. + + - `late_return` - The return was initiated too late and the receiving + institution has responded with a Late Return Claim. + - `wrong_payee_credit` - The check was deposited to the wrong payee and the + depositing institution has reimbursed the funds with a Wrong Payee Credit. + - `adjusted_amount` - The check was deposited with a different amount than what + was written on the check. + - `non_conforming_item` - The recipient was not able to process the check. This + usually happens for e.g., low quality images. + - `paid` - The check has already been deposited elsewhere and so this is a + duplicate. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not check_deposit_id: + raise ValueError(f"Expected a non-empty value for `check_deposit_id` but received {check_deposit_id!r}") + return self._post( + f"/simulations/check_deposits/{check_deposit_id}/adjustment", + body=maybe_transform( + { + "amount": amount, + "reason": reason, + }, + check_deposit_adjustment_params.CheckDepositAdjustmentParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CheckDeposit, + ) + def reject( self, check_deposit_id: str, @@ -131,6 +209,7 @@ def submit( self, check_deposit_id: str, *, + scan: check_deposit_submit_params.Scan | 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, @@ -146,6 +225,8 @@ def submit( Args: check_deposit_id: The identifier of the Check Deposit you wish to submit. + scan: If set, the simulation will use these values for the check's scanned MICR data. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -160,6 +241,7 @@ def submit( raise ValueError(f"Expected a non-empty value for `check_deposit_id` but received {check_deposit_id!r}") return self._post( f"/simulations/check_deposits/{check_deposit_id}/submit", + body=maybe_transform({"scan": scan}, check_deposit_submit_params.CheckDepositSubmitParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -191,6 +273,80 @@ def with_streaming_response(self) -> AsyncCheckDepositsResourceWithStreamingResp """ return AsyncCheckDepositsResourceWithStreamingResponse(self) + async def adjustment( + self, + check_deposit_id: str, + *, + amount: int | Omit = omit, + reason: Literal["late_return", "wrong_payee_credit", "adjusted_amount", "non_conforming_item", "paid"] + | 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, + idempotency_key: str | None = None, + ) -> CheckDeposit: + """ + Simulates the creation of a + [Check Deposit Adjustment](#check-deposit-adjustments) on a + [Check Deposit](#check-deposits). This Check Deposit must first have a `status` + of `submitted`. + + Args: + check_deposit_id: The identifier of the Check Deposit you wish to adjust. + + amount: The adjustment amount in the minor unit of the Check Deposit's currency (e.g., + cents). A negative amount means that the funds are being clawed back by the + other bank and is a debit to your account. Defaults to the negative of the Check + Deposit amount. + + reason: The reason for the adjustment. Defaults to `non_conforming_item`, which is often + used for a low quality image that the recipient wasn't able to handle. + + - `late_return` - The return was initiated too late and the receiving + institution has responded with a Late Return Claim. + - `wrong_payee_credit` - The check was deposited to the wrong payee and the + depositing institution has reimbursed the funds with a Wrong Payee Credit. + - `adjusted_amount` - The check was deposited with a different amount than what + was written on the check. + - `non_conforming_item` - The recipient was not able to process the check. This + usually happens for e.g., low quality images. + - `paid` - The check has already been deposited elsewhere and so this is a + duplicate. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not check_deposit_id: + raise ValueError(f"Expected a non-empty value for `check_deposit_id` but received {check_deposit_id!r}") + return await self._post( + f"/simulations/check_deposits/{check_deposit_id}/adjustment", + body=await async_maybe_transform( + { + "amount": amount, + "reason": reason, + }, + check_deposit_adjustment_params.CheckDepositAdjustmentParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=CheckDeposit, + ) + async def reject( self, check_deposit_id: str, @@ -283,6 +439,7 @@ async def submit( self, check_deposit_id: str, *, + scan: check_deposit_submit_params.Scan | 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, @@ -298,6 +455,8 @@ async def submit( Args: check_deposit_id: The identifier of the Check Deposit you wish to submit. + scan: If set, the simulation will use these values for the check's scanned MICR data. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -312,6 +471,7 @@ async def submit( raise ValueError(f"Expected a non-empty value for `check_deposit_id` but received {check_deposit_id!r}") return await self._post( f"/simulations/check_deposits/{check_deposit_id}/submit", + body=await async_maybe_transform({"scan": scan}, check_deposit_submit_params.CheckDepositSubmitParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -327,6 +487,9 @@ class CheckDepositsResourceWithRawResponse: def __init__(self, check_deposits: CheckDepositsResource) -> None: self._check_deposits = check_deposits + self.adjustment = to_raw_response_wrapper( + check_deposits.adjustment, + ) self.reject = to_raw_response_wrapper( check_deposits.reject, ) @@ -342,6 +505,9 @@ class AsyncCheckDepositsResourceWithRawResponse: def __init__(self, check_deposits: AsyncCheckDepositsResource) -> None: self._check_deposits = check_deposits + self.adjustment = async_to_raw_response_wrapper( + check_deposits.adjustment, + ) self.reject = async_to_raw_response_wrapper( check_deposits.reject, ) @@ -357,6 +523,9 @@ class CheckDepositsResourceWithStreamingResponse: def __init__(self, check_deposits: CheckDepositsResource) -> None: self._check_deposits = check_deposits + self.adjustment = to_streamed_response_wrapper( + check_deposits.adjustment, + ) self.reject = to_streamed_response_wrapper( check_deposits.reject, ) @@ -372,6 +541,9 @@ class AsyncCheckDepositsResourceWithStreamingResponse: def __init__(self, check_deposits: AsyncCheckDepositsResource) -> None: self._check_deposits = check_deposits + self.adjustment = async_to_streamed_response_wrapper( + check_deposits.adjustment, + ) self.reject = async_to_streamed_response_wrapper( check_deposits.reject, ) diff --git a/src/increase/resources/simulations/digital_wallet_token_requests.py b/src/increase/resources/simulations/digital_wallet_token_requests.py index 9b562ebe6..e7ff2dbb9 100644 --- a/src/increase/resources/simulations/digital_wallet_token_requests.py +++ b/src/increase/resources/simulations/digital_wallet_token_requests.py @@ -54,7 +54,7 @@ def create( idempotency_key: str | None = None, ) -> DigitalWalletTokenRequestCreateResponse: """ - Simulates a user attempting add a [Card](#cards) to a digital wallet such as + Simulates a user attempting to add a [Card](#cards) to a digital wallet such as Apple Pay. Args: @@ -119,7 +119,7 @@ async def create( idempotency_key: str | None = None, ) -> DigitalWalletTokenRequestCreateResponse: """ - Simulates a user attempting add a [Card](#cards) to a digital wallet such as + Simulates a user attempting to add a [Card](#cards) to a digital wallet such as Apple Pay. Args: diff --git a/src/increase/resources/simulations/inbound_check_deposits.py b/src/increase/resources/simulations/inbound_check_deposits.py index 3eb460566..cf30df066 100644 --- a/src/increase/resources/simulations/inbound_check_deposits.py +++ b/src/increase/resources/simulations/inbound_check_deposits.py @@ -17,7 +17,7 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.simulations import inbound_check_deposit_create_params +from ...types.simulations import inbound_check_deposit_create_params, inbound_check_deposit_adjustment_params from ...types.inbound_check_deposit import InboundCheckDeposit __all__ = ["InboundCheckDepositsResource", "AsyncInboundCheckDepositsResource"] @@ -62,10 +62,10 @@ def create( This imitates someone depositing a check at their bank that was issued from your account. It may or - may not be associated with a Check Transfer. Increase will evaluate the Check - Deposit as we would in production and either create a Transaction or a Declined - Transaction as a result. You can inspect the resulting Inbound Check Deposit - object to see the result. + may not be associated with a Check Transfer. Increase will evaluate the Inbound + Check Deposit as we would in production and either create a Transaction or a + Declined Transaction as a result. You can inspect the resulting Inbound Check + Deposit object to see the result. Args: account_number_id: The identifier of the Account Number the Inbound Check Deposit will be against. @@ -115,6 +115,78 @@ def create( cast_to=InboundCheckDeposit, ) + def adjustment( + self, + inbound_check_deposit_id: str, + *, + amount: int | Omit = omit, + reason: Literal["late_return", "wrong_payee_credit", "adjusted_amount", "non_conforming_item", "paid"] + | 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, + idempotency_key: str | None = None, + ) -> InboundCheckDeposit: + """Simulates an adjustment on an Inbound Check Deposit. + + The Inbound Check Deposit + must have a `status` of `accepted`. + + Args: + inbound_check_deposit_id: The identifier of the Inbound Check Deposit to adjust. + + amount: The adjustment amount in cents. Defaults to the amount of the Inbound Check + Deposit. + + reason: The reason for the adjustment. Defaults to `wrong_payee_credit`. + + - `late_return` - The return was initiated too late and the receiving + institution has responded with a Late Return Claim. + - `wrong_payee_credit` - The check was deposited to the wrong payee and the + depositing institution has reimbursed the funds with a Wrong Payee Credit. + - `adjusted_amount` - The check was deposited with a different amount than what + was written on the check. + - `non_conforming_item` - The recipient was not able to process the check. This + usually happens for e.g., low quality images. + - `paid` - The check has already been deposited elsewhere and so this is a + duplicate. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not inbound_check_deposit_id: + raise ValueError( + f"Expected a non-empty value for `inbound_check_deposit_id` but received {inbound_check_deposit_id!r}" + ) + return self._post( + f"/simulations/inbound_check_deposits/{inbound_check_deposit_id}/adjustment", + body=maybe_transform( + { + "amount": amount, + "reason": reason, + }, + inbound_check_deposit_adjustment_params.InboundCheckDepositAdjustmentParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=InboundCheckDeposit, + ) + class AsyncInboundCheckDepositsResource(AsyncAPIResource): @cached_property @@ -155,10 +227,10 @@ async def create( This imitates someone depositing a check at their bank that was issued from your account. It may or - may not be associated with a Check Transfer. Increase will evaluate the Check - Deposit as we would in production and either create a Transaction or a Declined - Transaction as a result. You can inspect the resulting Inbound Check Deposit - object to see the result. + may not be associated with a Check Transfer. Increase will evaluate the Inbound + Check Deposit as we would in production and either create a Transaction or a + Declined Transaction as a result. You can inspect the resulting Inbound Check + Deposit object to see the result. Args: account_number_id: The identifier of the Account Number the Inbound Check Deposit will be against. @@ -208,6 +280,78 @@ async def create( cast_to=InboundCheckDeposit, ) + async def adjustment( + self, + inbound_check_deposit_id: str, + *, + amount: int | Omit = omit, + reason: Literal["late_return", "wrong_payee_credit", "adjusted_amount", "non_conforming_item", "paid"] + | 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, + idempotency_key: str | None = None, + ) -> InboundCheckDeposit: + """Simulates an adjustment on an Inbound Check Deposit. + + The Inbound Check Deposit + must have a `status` of `accepted`. + + Args: + inbound_check_deposit_id: The identifier of the Inbound Check Deposit to adjust. + + amount: The adjustment amount in cents. Defaults to the amount of the Inbound Check + Deposit. + + reason: The reason for the adjustment. Defaults to `wrong_payee_credit`. + + - `late_return` - The return was initiated too late and the receiving + institution has responded with a Late Return Claim. + - `wrong_payee_credit` - The check was deposited to the wrong payee and the + depositing institution has reimbursed the funds with a Wrong Payee Credit. + - `adjusted_amount` - The check was deposited with a different amount than what + was written on the check. + - `non_conforming_item` - The recipient was not able to process the check. This + usually happens for e.g., low quality images. + - `paid` - The check has already been deposited elsewhere and so this is a + duplicate. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not inbound_check_deposit_id: + raise ValueError( + f"Expected a non-empty value for `inbound_check_deposit_id` but received {inbound_check_deposit_id!r}" + ) + return await self._post( + f"/simulations/inbound_check_deposits/{inbound_check_deposit_id}/adjustment", + body=await async_maybe_transform( + { + "amount": amount, + "reason": reason, + }, + inbound_check_deposit_adjustment_params.InboundCheckDepositAdjustmentParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=InboundCheckDeposit, + ) + class InboundCheckDepositsResourceWithRawResponse: def __init__(self, inbound_check_deposits: InboundCheckDepositsResource) -> None: @@ -216,6 +360,9 @@ def __init__(self, inbound_check_deposits: InboundCheckDepositsResource) -> None self.create = to_raw_response_wrapper( inbound_check_deposits.create, ) + self.adjustment = to_raw_response_wrapper( + inbound_check_deposits.adjustment, + ) class AsyncInboundCheckDepositsResourceWithRawResponse: @@ -225,6 +372,9 @@ def __init__(self, inbound_check_deposits: AsyncInboundCheckDepositsResource) -> self.create = async_to_raw_response_wrapper( inbound_check_deposits.create, ) + self.adjustment = async_to_raw_response_wrapper( + inbound_check_deposits.adjustment, + ) class InboundCheckDepositsResourceWithStreamingResponse: @@ -234,6 +384,9 @@ def __init__(self, inbound_check_deposits: InboundCheckDepositsResource) -> None self.create = to_streamed_response_wrapper( inbound_check_deposits.create, ) + self.adjustment = to_streamed_response_wrapper( + inbound_check_deposits.adjustment, + ) class AsyncInboundCheckDepositsResourceWithStreamingResponse: @@ -243,3 +396,6 @@ def __init__(self, inbound_check_deposits: AsyncInboundCheckDepositsResource) -> self.create = async_to_streamed_response_wrapper( inbound_check_deposits.create, ) + self.adjustment = async_to_streamed_response_wrapper( + inbound_check_deposits.adjustment, + ) diff --git a/src/increase/resources/simulations/programs.py b/src/increase/resources/simulations/programs.py index 23c617954..abf50b7f7 100644 --- a/src/increase/resources/simulations/programs.py +++ b/src/increase/resources/simulations/programs.py @@ -47,15 +47,8 @@ def create( self, *, name: str, - bank: Literal[ - "blue_ridge_bank", - "core_bank", - "first_internet_bank", - "global_innovations_bank", - "grasshopper_bank", - "twin_city_bank", - ] - | Omit = omit, + bank: Literal["core_bank", "first_internet_bank", "grasshopper_bank", "twin_city_bank"] | Omit = omit, + lending_maximum_extendable_credit: int | Omit = omit, reserve_account_id: str | 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. @@ -77,13 +70,13 @@ def create( bank: The bank for the program's accounts, defaults to First Internet Bank. - - `blue_ridge_bank` - Blue Ridge Bank, N.A. - `core_bank` - Core Bank - `first_internet_bank` - First Internet Bank of Indiana - - `global_innovations_bank` - Global Innovations Bank - `grasshopper_bank` - Grasshopper Bank - `twin_city_bank` - Twin City Bank + lending_maximum_extendable_credit: The maximum extendable credit of the program being added. + reserve_account_id: The identifier of the Account the Program should be added to is for. extra_headers: Send extra headers @@ -102,6 +95,7 @@ def create( { "name": name, "bank": bank, + "lending_maximum_extendable_credit": lending_maximum_extendable_credit, "reserve_account_id": reserve_account_id, }, program_create_params.ProgramCreateParams, @@ -141,15 +135,8 @@ async def create( self, *, name: str, - bank: Literal[ - "blue_ridge_bank", - "core_bank", - "first_internet_bank", - "global_innovations_bank", - "grasshopper_bank", - "twin_city_bank", - ] - | Omit = omit, + bank: Literal["core_bank", "first_internet_bank", "grasshopper_bank", "twin_city_bank"] | Omit = omit, + lending_maximum_extendable_credit: int | Omit = omit, reserve_account_id: str | 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. @@ -171,13 +158,13 @@ async def create( bank: The bank for the program's accounts, defaults to First Internet Bank. - - `blue_ridge_bank` - Blue Ridge Bank, N.A. - `core_bank` - Core Bank - `first_internet_bank` - First Internet Bank of Indiana - - `global_innovations_bank` - Global Innovations Bank - `grasshopper_bank` - Grasshopper Bank - `twin_city_bank` - Twin City Bank + lending_maximum_extendable_credit: The maximum extendable credit of the program being added. + reserve_account_id: The identifier of the Account the Program should be added to is for. extra_headers: Send extra headers @@ -196,6 +183,7 @@ async def create( { "name": name, "bank": bank, + "lending_maximum_extendable_credit": lending_maximum_extendable_credit, "reserve_account_id": reserve_account_id, }, program_create_params.ProgramCreateParams, diff --git a/src/increase/resources/simulations/simulations.py b/src/increase/resources/simulations/simulations.py index e5c83ebc7..3720f6d50 100644 --- a/src/increase/resources/simulations/simulations.py +++ b/src/increase/resources/simulations/simulations.py @@ -148,6 +148,14 @@ CardAuthorizationsResourceWithStreamingResponse, AsyncCardAuthorizationsResourceWithStreamingResponse, ) +from .card_authentications import ( + CardAuthenticationsResource, + AsyncCardAuthenticationsResource, + CardAuthenticationsResourceWithRawResponse, + AsyncCardAuthenticationsResourceWithRawResponse, + CardAuthenticationsResourceWithStreamingResponse, + AsyncCardAuthenticationsResourceWithStreamingResponse, +) from .pending_transactions import ( PendingTransactionsResource, AsyncPendingTransactionsResource, @@ -297,6 +305,10 @@ def card_fuel_confirmations(self) -> CardFuelConfirmationsResource: def card_refunds(self) -> CardRefundsResource: return CardRefundsResource(self._client) + @cached_property + def card_authentications(self) -> CardAuthenticationsResource: + return CardAuthenticationsResource(self._client) + @cached_property def card_disputes(self) -> CardDisputesResource: return CardDisputesResource(self._client) @@ -442,6 +454,10 @@ def card_fuel_confirmations(self) -> AsyncCardFuelConfirmationsResource: def card_refunds(self) -> AsyncCardRefundsResource: return AsyncCardRefundsResource(self._client) + @cached_property + def card_authentications(self) -> AsyncCardAuthenticationsResource: + return AsyncCardAuthenticationsResource(self._client) + @cached_property def card_disputes(self) -> AsyncCardDisputesResource: return AsyncCardDisputesResource(self._client) @@ -590,6 +606,10 @@ def card_fuel_confirmations(self) -> CardFuelConfirmationsResourceWithRawRespons def card_refunds(self) -> CardRefundsResourceWithRawResponse: return CardRefundsResourceWithRawResponse(self._simulations.card_refunds) + @cached_property + def card_authentications(self) -> CardAuthenticationsResourceWithRawResponse: + return CardAuthenticationsResourceWithRawResponse(self._simulations.card_authentications) + @cached_property def card_disputes(self) -> CardDisputesResourceWithRawResponse: return CardDisputesResourceWithRawResponse(self._simulations.card_disputes) @@ -723,6 +743,10 @@ def card_fuel_confirmations(self) -> AsyncCardFuelConfirmationsResourceWithRawRe def card_refunds(self) -> AsyncCardRefundsResourceWithRawResponse: return AsyncCardRefundsResourceWithRawResponse(self._simulations.card_refunds) + @cached_property + def card_authentications(self) -> AsyncCardAuthenticationsResourceWithRawResponse: + return AsyncCardAuthenticationsResourceWithRawResponse(self._simulations.card_authentications) + @cached_property def card_disputes(self) -> AsyncCardDisputesResourceWithRawResponse: return AsyncCardDisputesResourceWithRawResponse(self._simulations.card_disputes) @@ -856,6 +880,10 @@ def card_fuel_confirmations(self) -> CardFuelConfirmationsResourceWithStreamingR def card_refunds(self) -> CardRefundsResourceWithStreamingResponse: return CardRefundsResourceWithStreamingResponse(self._simulations.card_refunds) + @cached_property + def card_authentications(self) -> CardAuthenticationsResourceWithStreamingResponse: + return CardAuthenticationsResourceWithStreamingResponse(self._simulations.card_authentications) + @cached_property def card_disputes(self) -> CardDisputesResourceWithStreamingResponse: return CardDisputesResourceWithStreamingResponse(self._simulations.card_disputes) @@ -991,6 +1019,10 @@ def card_fuel_confirmations(self) -> AsyncCardFuelConfirmationsResourceWithStrea def card_refunds(self) -> AsyncCardRefundsResourceWithStreamingResponse: return AsyncCardRefundsResourceWithStreamingResponse(self._simulations.card_refunds) + @cached_property + def card_authentications(self) -> AsyncCardAuthenticationsResourceWithStreamingResponse: + return AsyncCardAuthenticationsResourceWithStreamingResponse(self._simulations.card_authentications) + @cached_property def card_disputes(self) -> AsyncCardDisputesResourceWithStreamingResponse: return AsyncCardDisputesResourceWithStreamingResponse(self._simulations.card_disputes) diff --git a/src/increase/resources/swift_transfers.py b/src/increase/resources/swift_transfers.py new file mode 100644 index 000000000..1573ac604 --- /dev/null +++ b/src/increase/resources/swift_transfers.py @@ -0,0 +1,714 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +from ..types import swift_transfer_list_params, swift_transfer_create_params +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..pagination import SyncPage, AsyncPage +from .._base_client import AsyncPaginator, make_request_options +from ..types.swift_transfer import SwiftTransfer + +__all__ = ["SwiftTransfersResource", "AsyncSwiftTransfersResource"] + + +class SwiftTransfersResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> SwiftTransfersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/Increase/increase-python#accessing-raw-response-data-eg-headers + """ + return SwiftTransfersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> SwiftTransfersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Increase/increase-python#with_streaming_response + """ + return SwiftTransfersResourceWithStreamingResponse(self) + + def create( + self, + *, + account_id: str, + account_number: str, + bank_identification_code: str, + creditor_address: swift_transfer_create_params.CreditorAddress, + creditor_name: str, + debtor_address: swift_transfer_create_params.DebtorAddress, + debtor_name: str, + instructed_amount: int, + instructed_currency: Literal["USD"], + source_account_number_id: str, + unstructured_remittance_information: str, + require_approval: bool | Omit = omit, + routing_number: str | 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, + idempotency_key: str | None = None, + ) -> SwiftTransfer: + """ + Create a Swift Transfer + + Args: + account_id: The identifier for the account that will send the transfer. + + account_number: The creditor's account number. + + bank_identification_code: The bank identification code (BIC) of the creditor. If it ends with the + three-character branch code, this must be 11 characters long. Otherwise this + must be 8 characters and the branch code will be assumed to be `XXX`. + + creditor_address: The creditor's address. + + creditor_name: The creditor's name. + + debtor_address: The debtor's address. + + debtor_name: The debtor's name. + + instructed_amount: The amount, in minor units of `instructed_currency`, to send to the creditor. + + instructed_currency: The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code of the + instructed amount. + + - `USD` - United States Dollar + + source_account_number_id: The Account Number to include in the transfer as the debtor's account number. + + unstructured_remittance_information: Unstructured remittance information to include in the transfer. + + require_approval: Whether the transfer requires explicit approval via the dashboard or API. + + routing_number: The creditor's bank account routing or transit number. Required in certain + countries. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return self._post( + "/swift_transfers", + body=maybe_transform( + { + "account_id": account_id, + "account_number": account_number, + "bank_identification_code": bank_identification_code, + "creditor_address": creditor_address, + "creditor_name": creditor_name, + "debtor_address": debtor_address, + "debtor_name": debtor_name, + "instructed_amount": instructed_amount, + "instructed_currency": instructed_currency, + "source_account_number_id": source_account_number_id, + "unstructured_remittance_information": unstructured_remittance_information, + "require_approval": require_approval, + "routing_number": routing_number, + }, + swift_transfer_create_params.SwiftTransferCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=SwiftTransfer, + ) + + def retrieve( + self, + swift_transfer_id: str, + *, + # 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, + ) -> SwiftTransfer: + """ + Retrieve a Swift Transfer + + Args: + swift_transfer_id: The identifier of the Swift Transfer. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not swift_transfer_id: + raise ValueError(f"Expected a non-empty value for `swift_transfer_id` but received {swift_transfer_id!r}") + return self._get( + f"/swift_transfers/{swift_transfer_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=SwiftTransfer, + ) + + def list( + self, + *, + account_id: str | Omit = omit, + created_at: swift_transfer_list_params.CreatedAt | Omit = omit, + cursor: str | Omit = omit, + idempotency_key: str | Omit = omit, + limit: int | Omit = omit, + status: swift_transfer_list_params.Status | 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, + ) -> SyncPage[SwiftTransfer]: + """ + List Swift Transfers + + Args: + account_id: Filter Swift Transfers to those that originated from the specified Account. + + cursor: Return the page of entries after this one. + + idempotency_key: Filter records to the one with the specified `idempotency_key` you chose for + that object. This value is unique across Increase and is used to ensure that a + request is only processed once. Learn more about + [idempotency](https://increase.com/documentation/idempotency-keys). + + limit: Limit the size of the list that is returned. The default (and maximum) is 100 + objects. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/swift_transfers", + page=SyncPage[SwiftTransfer], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "account_id": account_id, + "created_at": created_at, + "cursor": cursor, + "idempotency_key": idempotency_key, + "limit": limit, + "status": status, + }, + swift_transfer_list_params.SwiftTransferListParams, + ), + ), + model=SwiftTransfer, + ) + + def approve( + self, + swift_transfer_id: str, + *, + # 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, + idempotency_key: str | None = None, + ) -> SwiftTransfer: + """ + Approve a Swift Transfer + + Args: + swift_transfer_id: The identifier of the Swift Transfer to approve. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not swift_transfer_id: + raise ValueError(f"Expected a non-empty value for `swift_transfer_id` but received {swift_transfer_id!r}") + return self._post( + f"/swift_transfers/{swift_transfer_id}/approve", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=SwiftTransfer, + ) + + def cancel( + self, + swift_transfer_id: str, + *, + # 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, + idempotency_key: str | None = None, + ) -> SwiftTransfer: + """ + Cancel a pending Swift Transfer + + Args: + swift_transfer_id: The identifier of the pending Swift Transfer to cancel. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not swift_transfer_id: + raise ValueError(f"Expected a non-empty value for `swift_transfer_id` but received {swift_transfer_id!r}") + return self._post( + f"/swift_transfers/{swift_transfer_id}/cancel", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=SwiftTransfer, + ) + + +class AsyncSwiftTransfersResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncSwiftTransfersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/Increase/increase-python#accessing-raw-response-data-eg-headers + """ + return AsyncSwiftTransfersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncSwiftTransfersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Increase/increase-python#with_streaming_response + """ + return AsyncSwiftTransfersResourceWithStreamingResponse(self) + + async def create( + self, + *, + account_id: str, + account_number: str, + bank_identification_code: str, + creditor_address: swift_transfer_create_params.CreditorAddress, + creditor_name: str, + debtor_address: swift_transfer_create_params.DebtorAddress, + debtor_name: str, + instructed_amount: int, + instructed_currency: Literal["USD"], + source_account_number_id: str, + unstructured_remittance_information: str, + require_approval: bool | Omit = omit, + routing_number: str | 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, + idempotency_key: str | None = None, + ) -> SwiftTransfer: + """ + Create a Swift Transfer + + Args: + account_id: The identifier for the account that will send the transfer. + + account_number: The creditor's account number. + + bank_identification_code: The bank identification code (BIC) of the creditor. If it ends with the + three-character branch code, this must be 11 characters long. Otherwise this + must be 8 characters and the branch code will be assumed to be `XXX`. + + creditor_address: The creditor's address. + + creditor_name: The creditor's name. + + debtor_address: The debtor's address. + + debtor_name: The debtor's name. + + instructed_amount: The amount, in minor units of `instructed_currency`, to send to the creditor. + + instructed_currency: The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code of the + instructed amount. + + - `USD` - United States Dollar + + source_account_number_id: The Account Number to include in the transfer as the debtor's account number. + + unstructured_remittance_information: Unstructured remittance information to include in the transfer. + + require_approval: Whether the transfer requires explicit approval via the dashboard or API. + + routing_number: The creditor's bank account routing or transit number. Required in certain + countries. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return await self._post( + "/swift_transfers", + body=await async_maybe_transform( + { + "account_id": account_id, + "account_number": account_number, + "bank_identification_code": bank_identification_code, + "creditor_address": creditor_address, + "creditor_name": creditor_name, + "debtor_address": debtor_address, + "debtor_name": debtor_name, + "instructed_amount": instructed_amount, + "instructed_currency": instructed_currency, + "source_account_number_id": source_account_number_id, + "unstructured_remittance_information": unstructured_remittance_information, + "require_approval": require_approval, + "routing_number": routing_number, + }, + swift_transfer_create_params.SwiftTransferCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=SwiftTransfer, + ) + + async def retrieve( + self, + swift_transfer_id: str, + *, + # 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, + ) -> SwiftTransfer: + """ + Retrieve a Swift Transfer + + Args: + swift_transfer_id: The identifier of the Swift Transfer. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not swift_transfer_id: + raise ValueError(f"Expected a non-empty value for `swift_transfer_id` but received {swift_transfer_id!r}") + return await self._get( + f"/swift_transfers/{swift_transfer_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=SwiftTransfer, + ) + + def list( + self, + *, + account_id: str | Omit = omit, + created_at: swift_transfer_list_params.CreatedAt | Omit = omit, + cursor: str | Omit = omit, + idempotency_key: str | Omit = omit, + limit: int | Omit = omit, + status: swift_transfer_list_params.Status | 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, + ) -> AsyncPaginator[SwiftTransfer, AsyncPage[SwiftTransfer]]: + """ + List Swift Transfers + + Args: + account_id: Filter Swift Transfers to those that originated from the specified Account. + + cursor: Return the page of entries after this one. + + idempotency_key: Filter records to the one with the specified `idempotency_key` you chose for + that object. This value is unique across Increase and is used to ensure that a + request is only processed once. Learn more about + [idempotency](https://increase.com/documentation/idempotency-keys). + + limit: Limit the size of the list that is returned. The default (and maximum) is 100 + objects. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/swift_transfers", + page=AsyncPage[SwiftTransfer], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "account_id": account_id, + "created_at": created_at, + "cursor": cursor, + "idempotency_key": idempotency_key, + "limit": limit, + "status": status, + }, + swift_transfer_list_params.SwiftTransferListParams, + ), + ), + model=SwiftTransfer, + ) + + async def approve( + self, + swift_transfer_id: str, + *, + # 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, + idempotency_key: str | None = None, + ) -> SwiftTransfer: + """ + Approve a Swift Transfer + + Args: + swift_transfer_id: The identifier of the Swift Transfer to approve. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not swift_transfer_id: + raise ValueError(f"Expected a non-empty value for `swift_transfer_id` but received {swift_transfer_id!r}") + return await self._post( + f"/swift_transfers/{swift_transfer_id}/approve", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=SwiftTransfer, + ) + + async def cancel( + self, + swift_transfer_id: str, + *, + # 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, + idempotency_key: str | None = None, + ) -> SwiftTransfer: + """ + Cancel a pending Swift Transfer + + Args: + swift_transfer_id: The identifier of the pending Swift Transfer to cancel. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + if not swift_transfer_id: + raise ValueError(f"Expected a non-empty value for `swift_transfer_id` but received {swift_transfer_id!r}") + return await self._post( + f"/swift_transfers/{swift_transfer_id}/cancel", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=SwiftTransfer, + ) + + +class SwiftTransfersResourceWithRawResponse: + def __init__(self, swift_transfers: SwiftTransfersResource) -> None: + self._swift_transfers = swift_transfers + + self.create = to_raw_response_wrapper( + swift_transfers.create, + ) + self.retrieve = to_raw_response_wrapper( + swift_transfers.retrieve, + ) + self.list = to_raw_response_wrapper( + swift_transfers.list, + ) + self.approve = to_raw_response_wrapper( + swift_transfers.approve, + ) + self.cancel = to_raw_response_wrapper( + swift_transfers.cancel, + ) + + +class AsyncSwiftTransfersResourceWithRawResponse: + def __init__(self, swift_transfers: AsyncSwiftTransfersResource) -> None: + self._swift_transfers = swift_transfers + + self.create = async_to_raw_response_wrapper( + swift_transfers.create, + ) + self.retrieve = async_to_raw_response_wrapper( + swift_transfers.retrieve, + ) + self.list = async_to_raw_response_wrapper( + swift_transfers.list, + ) + self.approve = async_to_raw_response_wrapper( + swift_transfers.approve, + ) + self.cancel = async_to_raw_response_wrapper( + swift_transfers.cancel, + ) + + +class SwiftTransfersResourceWithStreamingResponse: + def __init__(self, swift_transfers: SwiftTransfersResource) -> None: + self._swift_transfers = swift_transfers + + self.create = to_streamed_response_wrapper( + swift_transfers.create, + ) + self.retrieve = to_streamed_response_wrapper( + swift_transfers.retrieve, + ) + self.list = to_streamed_response_wrapper( + swift_transfers.list, + ) + self.approve = to_streamed_response_wrapper( + swift_transfers.approve, + ) + self.cancel = to_streamed_response_wrapper( + swift_transfers.cancel, + ) + + +class AsyncSwiftTransfersResourceWithStreamingResponse: + def __init__(self, swift_transfers: AsyncSwiftTransfersResource) -> None: + self._swift_transfers = swift_transfers + + self.create = async_to_streamed_response_wrapper( + swift_transfers.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + swift_transfers.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + swift_transfers.list, + ) + self.approve = async_to_streamed_response_wrapper( + swift_transfers.approve, + ) + self.cancel = async_to_streamed_response_wrapper( + swift_transfers.cancel, + ) diff --git a/src/increase/resources/wire_drawdown_requests.py b/src/increase/resources/wire_drawdown_requests.py index ee73f74d0..76408df82 100644 --- a/src/increase/resources/wire_drawdown_requests.py +++ b/src/increase/resources/wire_drawdown_requests.py @@ -55,6 +55,7 @@ def create( debtor_account_number: str | Omit = omit, debtor_external_account_id: str | Omit = omit, debtor_routing_number: str | Omit = omit, + end_to_end_identification: str | 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, @@ -88,6 +89,9 @@ def create( debtor_routing_number: The debtor's routing number. + end_to_end_identification: A free-form reference string set by the sender mirrored back in the subsequent + wire transfer. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -112,6 +116,7 @@ def create( "debtor_account_number": debtor_account_number, "debtor_external_account_id": debtor_external_account_id, "debtor_routing_number": debtor_routing_number, + "end_to_end_identification": end_to_end_identification, }, wire_drawdown_request_create_params.WireDrawdownRequestCreateParams, ), @@ -253,6 +258,7 @@ async def create( debtor_account_number: str | Omit = omit, debtor_external_account_id: str | Omit = omit, debtor_routing_number: str | Omit = omit, + end_to_end_identification: str | 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, @@ -286,6 +292,9 @@ async def create( debtor_routing_number: The debtor's routing number. + end_to_end_identification: A free-form reference string set by the sender mirrored back in the subsequent + wire transfer. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -310,6 +319,7 @@ async def create( "debtor_account_number": debtor_account_number, "debtor_external_account_id": debtor_external_account_id, "debtor_routing_number": debtor_routing_number, + "end_to_end_identification": end_to_end_identification, }, wire_drawdown_request_create_params.WireDrawdownRequestCreateParams, ), diff --git a/src/increase/resources/wire_transfers.py b/src/increase/resources/wire_transfers.py index 080468288..c2a5a72f4 100644 --- a/src/increase/resources/wire_transfers.py +++ b/src/increase/resources/wire_transfers.py @@ -177,6 +177,7 @@ def list( external_account_id: str | Omit = omit, idempotency_key: str | Omit = omit, limit: int | Omit = omit, + status: wire_transfer_list_params.Status | 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, @@ -226,6 +227,7 @@ def list( "external_account_id": external_account_id, "idempotency_key": idempotency_key, "limit": limit, + "status": status, }, wire_transfer_list_params.WireTransferListParams, ), @@ -473,6 +475,7 @@ def list( external_account_id: str | Omit = omit, idempotency_key: str | Omit = omit, limit: int | Omit = omit, + status: wire_transfer_list_params.Status | 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, @@ -522,6 +525,7 @@ def list( "external_account_id": external_account_id, "idempotency_key": idempotency_key, "limit": limit, + "status": status, }, wire_transfer_list_params.WireTransferListParams, ), diff --git a/src/increase/types/__init__.py b/src/increase/types/__init__.py index c4fc145fa..3088a44b0 100644 --- a/src/increase/types/__init__.py +++ b/src/increase/types/__init__.py @@ -25,6 +25,7 @@ from .account_number import AccountNumber as AccountNumber from .balance_lookup import BalanceLookup as BalanceLookup from .check_transfer import CheckTransfer as CheckTransfer +from .swift_transfer import SwiftTransfer as SwiftTransfer from .card_iframe_url import CardIframeURL as CardIframeURL from .card_validation import CardValidation as CardValidation from .fednow_transfer import FednowTransfer as FednowTransfer @@ -61,10 +62,10 @@ from .entity_update_params import EntityUpdateParams as EntityUpdateParams from .export_create_params import ExportCreateParams as ExportCreateParams from .inbound_ach_transfer import InboundACHTransfer as InboundACHTransfer +from .unwrap_webhook_event import UnwrapWebhookEvent as UnwrapWebhookEvent from .account_create_params import AccountCreateParams as AccountCreateParams from .account_update_params import AccountUpdateParams as AccountUpdateParams from .bookkeeping_entry_set import BookkeepingEntrySet as BookkeepingEntrySet -from .entity_confirm_params import EntityConfirmParams as EntityConfirmParams from .inbound_check_deposit import InboundCheckDeposit as InboundCheckDeposit from .inbound_wire_transfer import InboundWireTransfer as InboundWireTransfer from .lockbox_create_params import LockboxCreateParams as LockboxCreateParams @@ -93,6 +94,7 @@ from .check_transfer_list_params import CheckTransferListParams as CheckTransferListParams from .intrafi_account_enrollment import IntrafiAccountEnrollment as IntrafiAccountEnrollment from .routing_number_list_params import RoutingNumberListParams as RoutingNumberListParams +from .swift_transfer_list_params import SwiftTransferListParams as SwiftTransferListParams from .card_validation_list_params import CardValidationListParams as CardValidationListParams from .check_deposit_create_params import CheckDepositCreateParams as CheckDepositCreateParams from .fednow_transfer_list_params import FednowTransferListParams as FednowTransferListParams @@ -103,12 +105,13 @@ from .account_number_create_params import AccountNumberCreateParams as AccountNumberCreateParams from .account_number_update_params import AccountNumberUpdateParams as AccountNumberUpdateParams from .account_transfer_list_params import AccountTransferListParams as AccountTransferListParams +from .card_dispute_withdraw_params import CardDisputeWithdrawParams as CardDisputeWithdrawParams from .check_transfer_create_params import CheckTransferCreateParams as CheckTransferCreateParams from .entity_supplemental_document import EntitySupplementalDocument as EntitySupplementalDocument -from .entity_update_address_params import EntityUpdateAddressParams as EntityUpdateAddressParams from .external_account_list_params import ExternalAccountListParams as ExternalAccountListParams from .oauth_connection_list_params import OAuthConnectionListParams as OAuthConnectionListParams from .routing_number_list_response import RoutingNumberListResponse as RoutingNumberListResponse +from .swift_transfer_create_params import SwiftTransferCreateParams as SwiftTransferCreateParams from .account_statement_list_params import AccountStatementListParams as AccountStatementListParams from .bookkeeping_entry_list_params import BookkeepingEntryListParams as BookkeepingEntryListParams from .card_validation_create_params import CardValidationCreateParams as CardValidationCreateParams @@ -150,7 +153,6 @@ from .bookkeeping_account_balance_params import BookkeepingAccountBalanceParams as BookkeepingAccountBalanceParams from .check_transfer_stop_payment_params import CheckTransferStopPaymentParams as CheckTransferStopPaymentParams from .digital_card_profile_create_params import DigitalCardProfileCreateParams as DigitalCardProfileCreateParams -from .entity_update_industry_code_params import EntityUpdateIndustryCodeParams as EntityUpdateIndustryCodeParams from .physical_card_profile_clone_params import PhysicalCardProfileCloneParams as PhysicalCardProfileCloneParams from .bookkeeping_entry_set_create_params import BookkeepingEntrySetCreateParams as BookkeepingEntrySetCreateParams from .inbound_ach_transfer_decline_params import InboundACHTransferDeclineParams as InboundACHTransferDeclineParams diff --git a/src/increase/types/account.py b/src/increase/types/account.py index a9d98010f..dfb6e00a3 100644 --- a/src/increase/types/account.py +++ b/src/increase/types/account.py @@ -8,7 +8,35 @@ from .._models import BaseModel -__all__ = ["Account"] +__all__ = ["Account", "Loan"] + + +class Loan(BaseModel): + """The Account's loan-related information, if the Account is a loan account.""" + + credit_limit: int + """The maximum amount of money that can be borrowed on the Account.""" + + grace_period_days: int + """ + The number of days after the statement date that the Account can be past due + before being considered delinquent. + """ + + maturity_date: Optional[date] = None + """The date on which the loan matures.""" + + statement_day_of_month: int + """The day of the month on which the loan statement is generated.""" + + statement_payment_type: Literal["balance", "interest_until_maturity"] + """The type of payment for the loan. + + - `balance` - The borrower must pay the full balance of the loan at the end of + the statement period. + - `interest_until_maturity` - The borrower must pay the accrued interest at the + end of the statement period. + """ class Account(BaseModel): @@ -59,6 +87,14 @@ class Account(BaseModel): entity_id: str """The identifier for the Entity the Account belongs to.""" + funding: Literal["loan", "deposits"] + """Whether the Account is funded by a loan or by deposits. + + - `loan` - An account funded by a loan. Before opening a loan account, contact + support@increase.com to set up a loan program. + - `deposits` - An account funded by deposits. + """ + idempotency_key: Optional[str] = None """The idempotency key you chose for this object. @@ -92,6 +128,9 @@ class Account(BaseModel): "0.01". """ + loan: Optional[Loan] = None + """The Account's loan-related information, if the Account is a loan account.""" + name: str """The name you choose for the Account.""" diff --git a/src/increase/types/account_create_params.py b/src/increase/types/account_create_params.py index 068dc2b51..705b76ebd 100644 --- a/src/increase/types/account_create_params.py +++ b/src/increase/types/account_create_params.py @@ -2,9 +2,13 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing import Union +from datetime import date +from typing_extensions import Literal, Required, Annotated, TypedDict -__all__ = ["AccountCreateParams"] +from .._utils import PropertyInfo + +__all__ = ["AccountCreateParams", "Loan"] class AccountCreateParams(TypedDict, total=False): @@ -14,14 +18,53 @@ class AccountCreateParams(TypedDict, total=False): entity_id: str """The identifier for the Entity that will own the Account.""" + funding: Literal["loan", "deposits"] + """Whether the Account is funded by a loan or by deposits. + + - `loan` - An account funded by a loan. Before opening a loan account, contact + support@increase.com to set up a loan program. + - `deposits` - An account funded by deposits. + """ + informational_entity_id: str """ The identifier of an Entity that, while not owning the Account, is associated with its activity. This is generally the beneficiary of the funds. """ + loan: Loan + """The loan details for the account.""" + program_id: str """The identifier for the Program that this Account falls under. Required if you operate more than one Program. """ + + +class Loan(TypedDict, total=False): + """The loan details for the account.""" + + credit_limit: Required[int] + """The maximum amount of money that can be drawn from the Account.""" + + grace_period_days: Required[int] + """ + The number of days after the statement date that the Account can be past due + before being considered delinquent. + """ + + statement_day_of_month: Required[int] + """The day of the month on which the loan statement is generated.""" + + statement_payment_type: Required[Literal["balance", "interest_until_maturity"]] + """The type of statement payment for the account. + + - `balance` - The borrower must pay the full balance of the loan at the end of + the statement period. + - `interest_until_maturity` - The borrower must pay the accrued interest at the + end of the statement period. + """ + + maturity_date: Annotated[Union[str, date], PropertyInfo(format="iso8601")] + """The date on which the loan matures.""" diff --git a/src/increase/types/account_statement.py b/src/increase/types/account_statement.py index f43fc0ea0..f1369ef82 100644 --- a/src/increase/types/account_statement.py +++ b/src/increase/types/account_statement.py @@ -1,14 +1,28 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict +from typing import Optional from datetime import datetime from typing_extensions import Literal -from pydantic import Field as FieldInfo - from .._models import BaseModel -__all__ = ["AccountStatement"] +__all__ = ["AccountStatement", "Loan"] + + +class Loan(BaseModel): + """The loan balances.""" + + due_at: Optional[datetime] = None + """ + The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) time at which the loan + payment is due. + """ + + due_balance: int + """The total amount due on the loan.""" + + past_due_balance: int + """The amount past due on the loan.""" class AccountStatement(BaseModel): @@ -30,11 +44,14 @@ class AccountStatement(BaseModel): """ ending_balance: int - """The Account's balance at the start of its statement period.""" + """The Account's balance at the end of its statement period.""" file_id: str """The identifier of the File containing a PDF of the statement.""" + loan: Optional[Loan] = None + """The loan balances.""" + starting_balance: int """The Account's balance at the start of its statement period.""" @@ -55,15 +72,3 @@ class AccountStatement(BaseModel): For this resource it will always be `account_statement`. """ - - if TYPE_CHECKING: - # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a - # value to this field, so for compatibility we avoid doing it at runtime. - __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> object: ... - else: - __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/account_transfer.py b/src/increase/types/account_transfer.py index 22ba640bd..13b58f2e5 100644 --- a/src/increase/types/account_transfer.py +++ b/src/increase/types/account_transfer.py @@ -79,9 +79,6 @@ class CreatedByUser(BaseModel): class CreatedBy(BaseModel): """What object created the transfer, either via the API or the dashboard.""" - api_key: Optional[CreatedByAPIKey] = None - """If present, details about the API key that created the transfer.""" - category: Literal["api_key", "oauth_application", "user"] """The type of object that created this transfer. @@ -92,6 +89,9 @@ class CreatedBy(BaseModel): object. """ + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + oauth_application: Optional[CreatedByOAuthApplication] = None """If present, details about the OAuth Application that created the transfer.""" diff --git a/src/increase/types/account_update_params.py b/src/increase/types/account_update_params.py index 32eaaba0f..6ce69dac3 100644 --- a/src/increase/types/account_update_params.py +++ b/src/increase/types/account_update_params.py @@ -2,17 +2,21 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing_extensions import Required, TypedDict -__all__ = ["AccountUpdateParams"] +__all__ = ["AccountUpdateParams", "Loan"] class AccountUpdateParams(TypedDict, total=False): - credit_limit: int - """ - The new credit limit of the Account, if and only if the Account is a loan - account. - """ + loan: Loan + """The loan details for the account.""" name: str """The new name of the Account.""" + + +class Loan(TypedDict, total=False): + """The loan details for the account.""" + + credit_limit: Required[int] + """The maximum amount of money that can be drawn from the Account.""" diff --git a/src/increase/types/ach_prenotification.py b/src/increase/types/ach_prenotification.py index 19afbc81b..96ae0d96b 100644 --- a/src/increase/types/ach_prenotification.py +++ b/src/increase/types/ach_prenotification.py @@ -171,24 +171,28 @@ class PrenotificationReturn(BaseModel): """Why the Prenotification was returned. - `insufficient_fund` - Code R01. Insufficient funds in the receiving account. - Sometimes abbreviated to NSF. + Sometimes abbreviated to "NSF." - `no_account` - Code R03. The account does not exist or the receiving bank was unable to locate it. - `account_closed` - Code R02. The account is closed at the receiving bank. - `invalid_account_number_structure` - Code R04. The account number is invalid at the receiving bank. - - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. The account - at the receiving bank was frozen per the Office of Foreign Assets Control. - - `credit_entry_refused_by_receiver` - Code R23. The receiving bank account - refused a credit transfer. + - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. This return + code has two separate meanings. (1) The receiving bank froze the account or + (2) the Office of Foreign Assets Control (OFAC) instructed the receiving bank + to return the entry. + - `credit_entry_refused_by_receiver` - Code R23. The receiving bank refused the + credit transfer. - `unauthorized_debit_to_consumer_account_using_corporate_sec_code` - Code R05. The receiving bank rejected because of an incorrect Standard Entry Class code. + Consumer accounts cannot be debited as `corporate_credit_or_debit` or + `corporate_trade_exchange`. - `corporate_customer_advised_not_authorized` - Code R29. The corporate customer at the receiving bank reversed the transfer. - `payment_stopped` - Code R08. The receiving bank stopped payment on this transfer. - - `non_transaction_account` - Code R20. The receiving bank account does not - perform transfers. + - `non_transaction_account` - Code R20. The account is not eligible for ACH, + such as a savings account with transaction limits. - `uncollected_funds` - Code R09. The receiving bank account does not have enough available balance for the transfer. - `routing_number_check_digit_error` - Code R28. The routing number is @@ -196,14 +200,13 @@ class PrenotificationReturn(BaseModel): - `customer_advised_unauthorized_improper_ineligible_or_incomplete` - Code R10. The customer at the receiving bank reversed the transfer. - `amount_field_error` - Code R19. The amount field is incorrect or too large. - - `authorization_revoked_by_customer` - Code R07. The customer at the receiving - institution informed their bank that they have revoked authorization for a - previously authorized transfer. + - `authorization_revoked_by_customer` - Code R07. The customer revoked their + authorization for a previously authorized transfer. - `invalid_ach_routing_number` - Code R13. The routing number is invalid. - `file_record_edit_criteria` - Code R17. The receiving bank is unable to process a field in the transfer. - - `enr_invalid_individual_name` - Code R45. The individual name field was - invalid. + - `enr_invalid_individual_name` - Code R45. A rare return reason. The individual + name field was invalid. - `returned_per_odfi_request` - Code R06. The originating financial institution asked for this transfer to be returned. The receiving bank is complying with the request. @@ -298,8 +301,8 @@ class PrenotificationReturn(BaseModel): a malformed credit entry. - `return_of_improper_debit_entry` - Code R35. A rare return reason. Return of a malformed debit entry. - - `return_of_xck_entry` - Code R33. A rare return reason. Return of a Destroyed - Check ("XKC") entry. + - `return_of_xck_entry` - Code R33. A rare return reason. Return of a destroyed + check ("XCK") entry. - `source_document_presented_for_payment` - Code R37. A rare return reason. The source document related to this ACH, usually an ACH check conversion, was presented to the bank. @@ -404,12 +407,22 @@ class ACHPrenotification(BaseModel): "internet_initiated", ] ] = None - """The Standard Entry Class (SEC) code to use for the ACH Prenotification. - - - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD). - - `corporate_trade_exchange` - Corporate Trade Exchange (CTX). - - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD). - - `internet_initiated` - Internet Initiated (WEB). + """ + The + [Standard Entry Class (SEC) code](/documentation/ach-standard-entry-class-codes) + to use for the ACH Prenotification. + + - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD) is used for + business-to-business payments. + - `corporate_trade_exchange` - Corporate Trade Exchange (CTX) allows for + including extensive remittance information with business-to-business payments. + - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD) + is used for credits or debits originated by an organization to a consumer, + such as payroll direct deposits. + - `internet_initiated` - Internet Initiated (WEB) is used for consumer payments + initiated or authorized via the Internet. Debits can only be initiated by + non-consumers to debit a consumer’s account. Credits can only be used for + consumer to consumer transactions. """ status: Literal["pending_submitting", "requires_attention", "returned", "submitted"] diff --git a/src/increase/types/ach_prenotification_create_params.py b/src/increase/types/ach_prenotification_create_params.py index d3b02fd90..9a2e83e89 100644 --- a/src/increase/types/ach_prenotification_create_params.py +++ b/src/increase/types/ach_prenotification_create_params.py @@ -67,10 +67,20 @@ class ACHPrenotificationCreateParams(TypedDict, total=False): "prearranged_payments_and_deposit", "internet_initiated", ] - """The Standard Entry Class (SEC) code to use for the ACH Prenotification. - - - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD). - - `corporate_trade_exchange` - Corporate Trade Exchange (CTX). - - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD). - - `internet_initiated` - Internet Initiated (WEB). + """ + The + [Standard Entry Class (SEC) code](/documentation/ach-standard-entry-class-codes) + to use for the ACH Prenotification. + + - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD) is used for + business-to-business payments. + - `corporate_trade_exchange` - Corporate Trade Exchange (CTX) allows for + including extensive remittance information with business-to-business payments. + - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD) + is used for credits or debits originated by an organization to a consumer, + such as payroll direct deposits. + - `internet_initiated` - Internet Initiated (WEB) is used for consumer payments + initiated or authorized via the Internet. Debits can only be initiated by + non-consumers to debit a consumer’s account. Credits can only be used for + consumer to consumer transactions. """ diff --git a/src/increase/types/ach_transfer.py b/src/increase/types/ach_transfer.py index 0639334bb..5616ebb2f 100644 --- a/src/increase/types/ach_transfer.py +++ b/src/increase/types/ach_transfer.py @@ -164,9 +164,6 @@ class CreatedByUser(BaseModel): class CreatedBy(BaseModel): """What object created the transfer, either via the API or the dashboard.""" - api_key: Optional[CreatedByAPIKey] = None - """If present, details about the API key that created the transfer.""" - category: Literal["api_key", "oauth_application", "user"] """The type of object that created this transfer. @@ -177,6 +174,9 @@ class CreatedBy(BaseModel): object. """ + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + oauth_application: Optional[CreatedByOAuthApplication] = None """If present, details about the OAuth Application that created the transfer.""" @@ -443,24 +443,28 @@ class Return(BaseModel): This reason code is sent by the receiving bank back to Increase. - `insufficient_fund` - Code R01. Insufficient funds in the receiving account. - Sometimes abbreviated to NSF. + Sometimes abbreviated to "NSF." - `no_account` - Code R03. The account does not exist or the receiving bank was unable to locate it. - `account_closed` - Code R02. The account is closed at the receiving bank. - `invalid_account_number_structure` - Code R04. The account number is invalid at the receiving bank. - - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. The account - at the receiving bank was frozen per the Office of Foreign Assets Control. - - `credit_entry_refused_by_receiver` - Code R23. The receiving bank account - refused a credit transfer. + - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. This return + code has two separate meanings. (1) The receiving bank froze the account or + (2) the Office of Foreign Assets Control (OFAC) instructed the receiving bank + to return the entry. + - `credit_entry_refused_by_receiver` - Code R23. The receiving bank refused the + credit transfer. - `unauthorized_debit_to_consumer_account_using_corporate_sec_code` - Code R05. The receiving bank rejected because of an incorrect Standard Entry Class code. + Consumer accounts cannot be debited as `corporate_credit_or_debit` or + `corporate_trade_exchange`. - `corporate_customer_advised_not_authorized` - Code R29. The corporate customer at the receiving bank reversed the transfer. - `payment_stopped` - Code R08. The receiving bank stopped payment on this transfer. - - `non_transaction_account` - Code R20. The receiving bank account does not - perform transfers. + - `non_transaction_account` - Code R20. The account is not eligible for ACH, + such as a savings account with transaction limits. - `uncollected_funds` - Code R09. The receiving bank account does not have enough available balance for the transfer. - `routing_number_check_digit_error` - Code R28. The routing number is @@ -468,14 +472,13 @@ class Return(BaseModel): - `customer_advised_unauthorized_improper_ineligible_or_incomplete` - Code R10. The customer at the receiving bank reversed the transfer. - `amount_field_error` - Code R19. The amount field is incorrect or too large. - - `authorization_revoked_by_customer` - Code R07. The customer at the receiving - institution informed their bank that they have revoked authorization for a - previously authorized transfer. + - `authorization_revoked_by_customer` - Code R07. The customer revoked their + authorization for a previously authorized transfer. - `invalid_ach_routing_number` - Code R13. The routing number is invalid. - `file_record_edit_criteria` - Code R17. The receiving bank is unable to process a field in the transfer. - - `enr_invalid_individual_name` - Code R45. The individual name field was - invalid. + - `enr_invalid_individual_name` - Code R45. A rare return reason. The individual + name field was invalid. - `returned_per_odfi_request` - Code R06. The originating financial institution asked for this transfer to be returned. The receiving bank is complying with the request. @@ -570,8 +573,8 @@ class Return(BaseModel): a malformed credit entry. - `return_of_improper_debit_entry` - Code R35. A rare return reason. Return of a malformed debit entry. - - `return_of_xck_entry` - Code R33. A rare return reason. Return of a Destroyed - Check ("XKC") entry. + - `return_of_xck_entry` - Code R33. A rare return reason. Return of a destroyed + check ("XCK") entry. - `source_document_presented_for_payment` - Code R37. A rare return reason. The source document related to this ACH, usually an ACH check conversion, was presented to the bank. @@ -657,7 +660,7 @@ class Submission(BaseModel): expected_funds_settlement_at: datetime.datetime """When the transfer is expected to settle in the recipient's account. - Credits may be available sooner, at the receiving banks discretion. The FedACH + Credits may be available sooner, at the receiving bank's discretion. The FedACH schedule is published [here](https://www.frbservices.org/resources/resource-centers/same-day-ach/fedach-processing-schedule.html). """ @@ -802,7 +805,7 @@ class ACHTransfer(BaseModel): individual_name: Optional[str] = None """The name of the transfer recipient. - This value is information and not verified by the recipient's bank. + This value is informational and not verified by the recipient's bank. """ network: Literal["ach"] @@ -848,12 +851,22 @@ class ACHTransfer(BaseModel): "prearranged_payments_and_deposit", "internet_initiated", ] - """The Standard Entry Class (SEC) code to use for the transfer. - - - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD). - - `corporate_trade_exchange` - Corporate Trade Exchange (CTX). - - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD). - - `internet_initiated` - Internet Initiated (WEB). + """ + The + [Standard Entry Class (SEC) code](/documentation/ach-standard-entry-class-codes) + to use for the transfer. + + - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD) is used for + business-to-business payments. + - `corporate_trade_exchange` - Corporate Trade Exchange (CTX) allows for + including extensive remittance information with business-to-business payments. + - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD) + is used for credits or debits originated by an organization to a consumer, + such as payroll direct deposits. + - `internet_initiated` - Internet Initiated (WEB) is used for consumer payments + initiated or authorized via the Internet. Debits can only be initiated by + non-consumers to debit a consumer’s account. Credits can only be used for + consumer to consumer transactions. """ statement_descriptor: str diff --git a/src/increase/types/ach_transfer_create_params.py b/src/increase/types/ach_transfer_create_params.py index ecb07fbbe..2b795a738 100644 --- a/src/increase/types/ach_transfer_create_params.py +++ b/src/increase/types/ach_transfer_create_params.py @@ -64,9 +64,10 @@ class ACHTransferCreateParams(TypedDict, total=False): """ company_entry_description: str - """A description of the transfer. - - This is included in the transfer data sent to the receiving bank. + """ + A description of the transfer, included in the transfer data sent to the + receiving bank. Standardized formatting may be required, for example `PAYROLL` + for payroll-related Prearranged Payments and Deposits (PPD) credit transfers. """ company_name: str @@ -132,12 +133,22 @@ class ACHTransferCreateParams(TypedDict, total=False): "prearranged_payments_and_deposit", "internet_initiated", ] - """The Standard Entry Class (SEC) code to use for the transfer. - - - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD). - - `corporate_trade_exchange` - Corporate Trade Exchange (CTX). - - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD). - - `internet_initiated` - Internet Initiated (WEB). + """ + The + [Standard Entry Class (SEC) code](/documentation/ach-standard-entry-class-codes) + to use for the transfer. + + - `corporate_credit_or_debit` - Corporate Credit and Debit (CCD) is used for + business-to-business payments. + - `corporate_trade_exchange` - Corporate Trade Exchange (CTX) allows for + including extensive remittance information with business-to-business payments. + - `prearranged_payments_and_deposit` - Prearranged Payments and Deposits (PPD) + is used for credits or debits originated by an organization to a consumer, + such as payroll direct deposits. + - `internet_initiated` - Internet Initiated (WEB) is used for consumer payments + initiated or authorized via the Internet. Debits can only be initiated by + non-consumers to debit a consumer’s account. Credits can only be used for + consumer to consumer transactions. """ transaction_timing: Literal["synchronous", "asynchronous"] diff --git a/src/increase/types/balance_lookup.py b/src/increase/types/balance_lookup.py index f8e1ee75b..53ca19549 100644 --- a/src/increase/types/balance_lookup.py +++ b/src/increase/types/balance_lookup.py @@ -1,13 +1,28 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict +from typing import Optional +from datetime import datetime from typing_extensions import Literal -from pydantic import Field as FieldInfo - from .._models import BaseModel -__all__ = ["BalanceLookup"] +__all__ = ["BalanceLookup", "Loan"] + + +class Loan(BaseModel): + """The loan balances for the Account.""" + + due_at: Optional[datetime] = None + """ + The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) time at which the loan + payment is due. + """ + + due_balance: int + """The total amount due on the loan.""" + + past_due_balance: int + """The amount past due on the loan.""" class BalanceLookup(BaseModel): @@ -30,20 +45,11 @@ class BalanceLookup(BaseModel): on the Account. """ + loan: Optional[Loan] = None + """The loan balances for the Account.""" + type: Literal["balance_lookup"] """A constant representing the object's type. For this resource it will always be `balance_lookup`. """ - - if TYPE_CHECKING: - # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a - # value to this field, so for compatibility we avoid doing it at runtime. - __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> object: ... - else: - __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/bookkeeping_balance_lookup.py b/src/increase/types/bookkeeping_balance_lookup.py index bcd350e84..e41891c38 100644 --- a/src/increase/types/bookkeeping_balance_lookup.py +++ b/src/increase/types/bookkeeping_balance_lookup.py @@ -9,7 +9,7 @@ class BookkeepingBalanceLookup(BaseModel): """ - Represents a request to lookup the balance of an Bookkeeping Account at a given point in time. + Represents a request to lookup the balance of a Bookkeeping Account at a given point in time. """ balance: int diff --git a/src/increase/types/bookkeeping_entry.py b/src/increase/types/bookkeeping_entry.py index 06aed0aaa..5ccd70acb 100644 --- a/src/increase/types/bookkeeping_entry.py +++ b/src/increase/types/bookkeeping_entry.py @@ -30,7 +30,7 @@ class BookkeepingEntry(BaseModel): """When the entry set was created.""" entry_set_id: str - """The identifier for the Account the Entry belongs to.""" + """The identifier for the Entry Set the Entry belongs to.""" type: Literal["bookkeeping_entry"] """A constant representing the object's type. diff --git a/src/increase/types/card_dispute.py b/src/increase/types/card_dispute.py index adc6f294b..146616e14 100644 --- a/src/increase/types/card_dispute.py +++ b/src/increase/types/card_dispute.py @@ -105,6 +105,7 @@ "VisaUserSubmissionUserPrearbitration", "VisaUserSubmissionUserPrearbitrationCategoryChange", "Win", + "Withdrawal", ] @@ -801,6 +802,15 @@ class VisaNetworkEvent(BaseModel): Network Event: details will be under the `user_withdrawal_submitted` object. """ + created_at: datetime + """ + The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which + the Visa Card Dispute Network Event was created. + """ + + dispute_financial_transaction_id: Optional[str] = None + """The dispute financial transaction that resulted from the network event, if any.""" + chargeback_accepted: Optional[VisaNetworkEventChargebackAccepted] = None """A Card Dispute Chargeback Accepted Visa Network Event object. @@ -828,15 +838,6 @@ class VisaNetworkEvent(BaseModel): has timed out in the user's favor. """ - created_at: datetime - """ - The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which - the Visa Card Dispute Network Event was created. - """ - - dispute_financial_transaction_id: Optional[str] = None - """The dispute financial transaction that resulted from the network event, if any.""" - merchant_prearbitration_decline_submitted: Optional[VisaNetworkEventMerchantPrearbitrationDeclineSubmitted] = None """ A Card Dispute Merchant Pre-Arbitration Decline Submitted Visa Network Event @@ -2522,14 +2523,6 @@ class VisaUserSubmission(BaseModel): Submission: details will be under the `user_prearbitration` object. """ - chargeback: Optional[VisaUserSubmissionChargeback] = None - """A Visa Card Dispute Chargeback User Submission Chargeback Details object. - - This field will be present in the JSON response if and only if `category` is - equal to `chargeback`. Contains the details specific to a Visa chargeback User - Submission for a Card Dispute. - """ - created_at: datetime """ The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which @@ -2554,14 +2547,6 @@ class VisaUserSubmission(BaseModel): Visa Card Dispute. """ - merchant_prearbitration_decline: Optional[VisaUserSubmissionMerchantPrearbitrationDecline] = None - """A Visa Card Dispute Merchant Pre-Arbitration Decline User Submission object. - - This field will be present in the JSON response if and only if `category` is - equal to `merchant_prearbitration_decline`. Contains the details specific to a - merchant prearbitration decline Visa Card Dispute User Submission. - """ - status: Literal["abandoned", "accepted", "further_information_requested", "pending_reviewing"] """The status of the Visa Card Dispute User Submission. @@ -2578,6 +2563,22 @@ class VisaUserSubmission(BaseModel): the Visa Card Dispute User Submission was updated. """ + chargeback: Optional[VisaUserSubmissionChargeback] = None + """A Visa Card Dispute Chargeback User Submission Chargeback Details object. + + This field will be present in the JSON response if and only if `category` is + equal to `chargeback`. Contains the details specific to a Visa chargeback User + Submission for a Card Dispute. + """ + + merchant_prearbitration_decline: Optional[VisaUserSubmissionMerchantPrearbitrationDecline] = None + """A Visa Card Dispute Merchant Pre-Arbitration Decline User Submission object. + + This field will be present in the JSON response if and only if `category` is + equal to `merchant_prearbitration_decline`. Contains the details specific to a + merchant prearbitration decline Visa Card Dispute User Submission. + """ + user_prearbitration: Optional[VisaUserSubmissionUserPrearbitration] = None """A Visa Card Dispute User-Initiated Pre-Arbitration User Submission object. @@ -2627,6 +2628,15 @@ class Win(BaseModel): """ +class Withdrawal(BaseModel): + """ + If the Card Dispute has been withdrawn, this will contain details of the withdrawal. + """ + + explanation: Optional[str] = None + """The explanation for the withdrawal of the Card Dispute.""" + + class CardDispute(BaseModel): """ If unauthorized activity occurs on a card, you can create a Card Dispute and we'll work with the card networks to return the funds if appropriate. @@ -2722,3 +2732,9 @@ class CardDispute(BaseModel): If the Card Dispute's status is `won`, this will contain details of the won dispute. """ + + withdrawal: Optional[Withdrawal] = None + """ + If the Card Dispute has been withdrawn, this will contain details of the + withdrawal. + """ diff --git a/src/increase/types/card_dispute_withdraw_params.py b/src/increase/types/card_dispute_withdraw_params.py new file mode 100644 index 000000000..ac79a2e8e --- /dev/null +++ b/src/increase/types/card_dispute_withdraw_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["CardDisputeWithdrawParams"] + + +class CardDisputeWithdrawParams(TypedDict, total=False): + explanation: str + """The explanation for withdrawing the Card Dispute.""" diff --git a/src/increase/types/card_payment.py b/src/increase/types/card_payment.py index ad45d6e3a..de29add58 100644 --- a/src/increase/types/card_payment.py +++ b/src/increase/types/card_payment.py @@ -14,6 +14,9 @@ "ElementCardAuthentication", "ElementCardAuthenticationChallenge", "ElementCardAuthenticationChallengeAttempt", + "ElementCardAuthenticationDeviceChannel", + "ElementCardAuthenticationDeviceChannelBrowser", + "ElementCardAuthenticationDeviceChannelMerchantInitiated", "ElementCardAuthorization", "ElementCardAuthorizationAdditionalAmounts", "ElementCardAuthorizationAdditionalAmountsClinic", @@ -33,6 +36,7 @@ "ElementCardAuthorizationVerification", "ElementCardAuthorizationVerificationCardVerificationCode", "ElementCardAuthorizationVerificationCardholderAddress", + "ElementCardAuthorizationVerificationCardholderName", "ElementCardAuthorizationExpiration", "ElementCardBalanceInquiry", "ElementCardBalanceInquiryAdditionalAmounts", @@ -53,6 +57,7 @@ "ElementCardBalanceInquiryVerification", "ElementCardBalanceInquiryVerificationCardVerificationCode", "ElementCardBalanceInquiryVerificationCardholderAddress", + "ElementCardBalanceInquiryVerificationCardholderName", "ElementCardDecline", "ElementCardDeclineAdditionalAmounts", "ElementCardDeclineAdditionalAmountsClinic", @@ -72,6 +77,7 @@ "ElementCardDeclineVerification", "ElementCardDeclineVerificationCardVerificationCode", "ElementCardDeclineVerificationCardholderAddress", + "ElementCardDeclineVerificationCardholderName", "ElementCardFinancial", "ElementCardFinancialAdditionalAmounts", "ElementCardFinancialAdditionalAmountsClinic", @@ -91,6 +97,7 @@ "ElementCardFinancialVerification", "ElementCardFinancialVerificationCardVerificationCode", "ElementCardFinancialVerificationCardholderAddress", + "ElementCardFinancialVerificationCardholderName", "ElementCardFuelConfirmation", "ElementCardFuelConfirmationNetworkIdentifiers", "ElementCardIncrement", @@ -150,7 +157,9 @@ "ElementCardValidationVerification", "ElementCardValidationVerificationCardVerificationCode", "ElementCardValidationVerificationCardholderAddress", + "ElementCardValidationVerificationCardholderName", "ElementOther", + "SchemeFee", "State", ] @@ -200,6 +209,96 @@ class ElementCardAuthenticationChallenge(BaseModel): """ +class ElementCardAuthenticationDeviceChannelBrowser(BaseModel): + """Fields specific to the browser device channel.""" + + accept_header: Optional[str] = None + """The accept header from the cardholder's browser.""" + + ip_address: Optional[str] = None + """The IP address of the cardholder's browser.""" + + javascript_enabled: Optional[Literal["enabled", "disabled"]] = None + """Whether JavaScript is enabled in the cardholder's browser. + + - `enabled` - JavaScript is enabled in the cardholder's browser. + - `disabled` - JavaScript is not enabled in the cardholder's browser. + """ + + language: Optional[str] = None + """The language of the cardholder's browser.""" + + user_agent: Optional[str] = None + """The user agent of the cardholder's browser.""" + + +class ElementCardAuthenticationDeviceChannelMerchantInitiated(BaseModel): + """Fields specific to merchant initiated transactions.""" + + indicator: Literal[ + "recurring_transaction", + "installment_transaction", + "add_card", + "maintain_card_information", + "account_verification", + "split_delayed_shipment", + "top_up", + "mail_order", + "telephone_order", + "whitelist_status_check", + "other_payment", + "billing_agreement", + "device_binding_status_check", + "card_security_code_status_check", + "delayed_shipment", + "split_payment", + "fido_credential_deletion", + "fido_credential_registration", + "decoupled_authentication_fallback", + ] + """The merchant initiated indicator for the transaction. + + - `recurring_transaction` - Recurring transaction. + - `installment_transaction` - Installment transaction. + - `add_card` - Add card. + - `maintain_card_information` - Maintain card information. + - `account_verification` - Account verification. + - `split_delayed_shipment` - Split or delayed shipment. + - `top_up` - Top up. + - `mail_order` - Mail order. + - `telephone_order` - Telephone order. + - `whitelist_status_check` - Whitelist status check. + - `other_payment` - Other payment. + - `billing_agreement` - Billing agreement. + - `device_binding_status_check` - Device binding status check. + - `card_security_code_status_check` - Card security code status check. + - `delayed_shipment` - Delayed shipment. + - `split_payment` - Split payment. + - `fido_credential_deletion` - FIDO credential deletion. + - `fido_credential_registration` - FIDO credential registration. + - `decoupled_authentication_fallback` - Decoupled authentication fallback. + """ + + +class ElementCardAuthenticationDeviceChannel(BaseModel): + """The device channel of the card authentication attempt.""" + + browser: Optional[ElementCardAuthenticationDeviceChannelBrowser] = None + """Fields specific to the browser device channel.""" + + category: Literal["app", "browser", "three_ds_requestor_initiated"] + """The category of the device channel. + + - `app` - The authentication attempt was made from an app. + - `browser` - The authentication attempt was made from a browser. + - `three_ds_requestor_initiated` - The authentication attempt was initiated by + the 3DS Requestor. + """ + + merchant_initiated: Optional[ElementCardAuthenticationDeviceChannelMerchantInitiated] = None + """Fields specific to merchant initiated transactions.""" + + class ElementCardAuthentication(BaseModel): """A Card Authentication object. @@ -209,12 +308,66 @@ class ElementCardAuthentication(BaseModel): id: str """The Card Authentication identifier.""" + access_control_server_transaction_id: str + """ + A unique identifier assigned by the Access Control Server (us) for this + transaction. + """ + + billing_address_city: Optional[str] = None + """ + The city of the cardholder billing address associated with the card used for + this purchase. + """ + + billing_address_country: Optional[str] = None + """ + The country of the cardholder billing address associated with the card used for + this purchase. + """ + + billing_address_line1: Optional[str] = None + """ + The first line of the cardholder billing address associated with the card used + for this purchase. + """ + + billing_address_line2: Optional[str] = None + """ + The second line of the cardholder billing address associated with the card used + for this purchase. + """ + + billing_address_line3: Optional[str] = None + """ + The third line of the cardholder billing address associated with the card used + for this purchase. + """ + + billing_address_postal_code: Optional[str] = None + """ + The postal code of the cardholder billing address associated with the card used + for this purchase. + """ + + billing_address_state: Optional[str] = None + """ + The US state of the cardholder billing address associated with the card used for + this purchase. + """ + card_id: str """The identifier of the Card.""" card_payment_id: str """The ID of the Card Payment this transaction belongs to.""" + cardholder_email: Optional[str] = None + """The email address of the cardholder.""" + + cardholder_name: Optional[str] = None + """The name of the cardholder.""" + category: Optional[Literal["payment_authentication", "non_payment_authentication"]] = None """The category of the card authentication attempt. @@ -252,13 +405,13 @@ class ElementCardAuthentication(BaseModel): - `webhook_timed_out` - The webhook timed out. """ - device_channel: Optional[Literal["app", "browser", "three_ds_requestor_initiated"]] = None - """The device channel of the card authentication attempt. + device_channel: ElementCardAuthenticationDeviceChannel + """The device channel of the card authentication attempt.""" - - `app` - The authentication attempt was made from an app. - - `browser` - The authentication attempt was made from a browser. - - `three_ds_requestor_initiated` - The authentication attempt was initiated by - the 3DS Requestor. + directory_server_transaction_id: str + """ + A unique identifier assigned by the Directory Server (the card network) for this + transaction. """ merchant_acceptor_id: str @@ -279,9 +432,21 @@ class ElementCardAuthentication(BaseModel): merchant_name: str """The name of the merchant.""" + prior_card_authentication_id: Optional[str] = None + """ + The ID of a prior Card Authentication that the requestor used to authenticate + this cardholder for a previous transaction. + """ + purchase_amount: Optional[int] = None """The purchase amount in minor units.""" + purchase_amount_cardholder_estimated: Optional[int] = None + """ + The purchase amount in the cardholder's currency (i.e., USD) estimated using + daily conversion rates from the card network. + """ + purchase_currency: Optional[str] = None """ The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the @@ -294,6 +459,91 @@ class ElementCardAuthentication(BaseModel): authentication attempt. """ + requestor_authentication_indicator: Optional[ + Literal[ + "payment_transaction", + "recurring_transaction", + "installment_transaction", + "add_card", + "maintain_card", + "emv_token_cardholder_verification", + "billing_agreement", + ] + ] = None + """ + The 3DS requestor authentication indicator describes why the authentication + attempt is performed, such as for a recurring transaction. + + - `payment_transaction` - The authentication is for a payment transaction. + - `recurring_transaction` - The authentication is for a recurring transaction. + - `installment_transaction` - The authentication is for an installment + transaction. + - `add_card` - The authentication is for adding a card. + - `maintain_card` - The authentication is for maintaining a card. + - `emv_token_cardholder_verification` - The authentication is for EMV token + cardholder verification. + - `billing_agreement` - The authentication is for a billing agreement. + """ + + requestor_challenge_indicator: Optional[ + Literal[ + "no_preference", + "no_challenge_requested", + "challenge_requested_3ds_requestor_preference", + "challenge_requested_mandate", + "no_challenge_requested_transactional_risk_analysis_already_performed", + "no_challenge_requested_data_share_only", + "no_challenge_requested_strong_consumer_authentication_already_performed", + "no_challenge_requested_utilize_whitelist_exemption_if_no_challenge_required", + "challenge_requested_whitelist_prompt_requested_if_challenge_required", + ] + ] = None + """Indicates whether a challenge is requested for this transaction. + + - `no_preference` - No preference. + - `no_challenge_requested` - No challenge requested. + - `challenge_requested_3ds_requestor_preference` - Challenge requested, 3DS + Requestor preference. + - `challenge_requested_mandate` - Challenge requested, mandate. + - `no_challenge_requested_transactional_risk_analysis_already_performed` - No + challenge requested, transactional risk analysis already performed. + - `no_challenge_requested_data_share_only` - No challenge requested, data share + only. + - `no_challenge_requested_strong_consumer_authentication_already_performed` - No + challenge requested, strong consumer authentication already performed. + - `no_challenge_requested_utilize_whitelist_exemption_if_no_challenge_required` - + No challenge requested, utilize whitelist exemption if no challenge required. + - `challenge_requested_whitelist_prompt_requested_if_challenge_required` - + Challenge requested, whitelist prompt requested if challenge required. + """ + + requestor_name: str + """The name of the 3DS requestor.""" + + requestor_url: str + """The URL of the 3DS requestor.""" + + shipping_address_city: Optional[str] = None + """The city of the shipping address associated with this purchase.""" + + shipping_address_country: Optional[str] = None + """The country of the shipping address associated with this purchase.""" + + shipping_address_line1: Optional[str] = None + """The first line of the shipping address associated with this purchase.""" + + shipping_address_line2: Optional[str] = None + """The second line of the shipping address associated with this purchase.""" + + shipping_address_line3: Optional[str] = None + """The third line of the shipping address associated with this purchase.""" + + shipping_address_postal_code: Optional[str] = None + """The postal code of the shipping address associated with this purchase.""" + + shipping_address_state: Optional[str] = None + """The US state of the shipping address associated with this purchase.""" + status: Literal[ "denied", "authenticated_with_challenge", @@ -322,6 +572,30 @@ class ElementCardAuthentication(BaseModel): threshold. """ + three_d_secure_server_transaction_id: str + """ + A unique identifier assigned by the 3DS Server initiating the authentication + attempt for this transaction. + """ + + transaction_type: Optional[ + Literal[ + "goods_service_purchase", + "check_acceptance", + "account_funding", + "quasi_cash_transaction", + "prepaid_activation_and_load", + ] + ] = None + """The type of transaction being authenticated. + + - `goods_service_purchase` - Purchase of goods or services. + - `check_acceptance` - Check acceptance. + - `account_funding` - Account funding. + - `quasi_cash_transaction` - Quasi-cash transaction. + - `prepaid_activation_and_load` - Prepaid activation and load. + """ + type: Literal["card_authentication"] """A constant representing the object's type. @@ -645,6 +919,7 @@ class ElementCardAuthorizationNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -659,8 +934,10 @@ class ElementCardAuthorizationNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -676,6 +953,41 @@ class ElementCardAuthorizationNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class ElementCardAuthorizationNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -781,6 +1093,19 @@ class ElementCardAuthorizationVerificationCardholderAddress(BaseModel): """ +class ElementCardAuthorizationVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class ElementCardAuthorizationVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -796,11 +1121,14 @@ class ElementCardAuthorizationVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[ElementCardAuthorizationVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class ElementCardAuthorization(BaseModel): """A Card Authorization object. - This field will be present in the JSON response if and only if `category` is equal to `card_authorization`. Card Authorizations are temporary holds placed on a customers funds with the intent to later clear a transaction. + This field will be present in the JSON response if and only if `category` is equal to `card_authorization`. Card Authorizations are temporary holds placed on a customer's funds with the intent to later clear a transaction. """ id: str @@ -1354,6 +1682,7 @@ class ElementCardBalanceInquiryNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -1368,8 +1697,10 @@ class ElementCardBalanceInquiryNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -1385,6 +1716,41 @@ class ElementCardBalanceInquiryNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class ElementCardBalanceInquiryNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -1490,6 +1856,19 @@ class ElementCardBalanceInquiryVerificationCardholderAddress(BaseModel): """ +class ElementCardBalanceInquiryVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class ElementCardBalanceInquiryVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -1505,6 +1884,9 @@ class ElementCardBalanceInquiryVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[ElementCardBalanceInquiryVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class ElementCardBalanceInquiry(BaseModel): """A Card Balance Inquiry object. @@ -1934,6 +2316,7 @@ class ElementCardDeclineNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -1948,8 +2331,10 @@ class ElementCardDeclineNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -1965,6 +2350,41 @@ class ElementCardDeclineNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class ElementCardDeclineNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -2070,6 +2490,19 @@ class ElementCardDeclineVerificationCardholderAddress(BaseModel): """ +class ElementCardDeclineVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class ElementCardDeclineVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -2085,6 +2518,9 @@ class ElementCardDeclineVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[ElementCardDeclineVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class ElementCardDecline(BaseModel): """A Card Decline object. @@ -2307,6 +2743,7 @@ class ElementCardDecline(BaseModel): "declined_by_stand_in_processing", "invalid_physical_card", "missing_original_authorization", + "invalid_cryptogram", "failed_3ds_authentication", "suspected_card_testing", "suspected_fraud", @@ -2332,10 +2769,12 @@ class ElementCardDecline(BaseModel): - `webhook_timed_out` - Your application webhook did not respond without the required timeout. - `declined_by_stand_in_processing` - Declined by stand-in processing. - - `invalid_physical_card` - The card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The card read had an invalid CVV or dCVV. - `missing_original_authorization` - The original card authorization for this incremental authorization does not exist. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `failed_3ds_authentication` - The transaction was declined because the 3DS authentication failed. - `suspected_card_testing` - The transaction was suspected to be used by a card @@ -2670,6 +3109,7 @@ class ElementCardFinancialNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -2684,8 +3124,10 @@ class ElementCardFinancialNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -2701,6 +3143,41 @@ class ElementCardFinancialNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class ElementCardFinancialNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -2806,6 +3283,19 @@ class ElementCardFinancialVerificationCardholderAddress(BaseModel): """ +class ElementCardFinancialVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class ElementCardFinancialVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -2821,11 +3311,14 @@ class ElementCardFinancialVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[ElementCardFinancialVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class ElementCardFinancial(BaseModel): """A Card Financial object. - This field will be present in the JSON response if and only if `category` is equal to `card_financial`. Card Financials are temporary holds placed on a customers funds with the intent to later clear a transaction. + This field will be present in the JSON response if and only if `category` is equal to `card_financial`. Card Financials are temporary holds placed on a customer's funds with the intent to later clear a transaction. """ id: str @@ -3474,7 +3967,7 @@ class ElementCardRefundCashback(BaseModel): class ElementCardRefundInterchange(BaseModel): - """Interchange assessed as a part of this transaciton.""" + """Interchange assessed as a part of this transaction.""" amount: str """ @@ -3943,7 +4436,7 @@ class ElementCardRefundPurchaseDetails(BaseModel): class ElementCardRefund(BaseModel): """A Card Refund object. - This field will be present in the JSON response if and only if `category` is equal to `card_refund`. Card Refunds move money back to the cardholder. While they are usually connected to a Card Settlement an acquirer can also refund money directly to a card without relation to a transaction. + This field will be present in the JSON response if and only if `category` is equal to `card_refund`. Card Refunds move money back to the cardholder. While they are usually connected to a Card Settlement, an acquirer can also refund money directly to a card without relation to a transaction. """ id: str @@ -3973,7 +4466,7 @@ class ElementCardRefund(BaseModel): """ interchange: Optional[ElementCardRefundInterchange] = None - """Interchange assessed as a part of this transaciton.""" + """Interchange assessed as a part of this transaction.""" merchant_acceptor_id: str """ @@ -4693,7 +5186,7 @@ class ElementCardSettlementPurchaseDetails(BaseModel): class ElementCardSettlementSurcharge(BaseModel): """Surcharge amount details, if applicable. - The amount is positive if the surcharge is added to to the overall transaction amount (surcharge), and negative if the surcharge is deducted from the overall transaction amount (discount). + The amount is positive if the surcharge is added to the overall transaction amount (surcharge), and negative if the surcharge is deducted from the overall transaction amount (discount). """ amount: int @@ -4804,7 +5297,7 @@ class ElementCardSettlement(BaseModel): surcharge: Optional[ElementCardSettlementSurcharge] = None """Surcharge amount details, if applicable. - The amount is positive if the surcharge is added to to the overall transaction + The amount is positive if the surcharge is added to the overall transaction amount (surcharge), and negative if the surcharge is deducted from the overall transaction amount (discount). """ @@ -5135,6 +5628,7 @@ class ElementCardValidationNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -5149,8 +5643,10 @@ class ElementCardValidationNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -5166,6 +5662,41 @@ class ElementCardValidationNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class ElementCardValidationNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -5271,6 +5802,19 @@ class ElementCardValidationVerificationCardholderAddress(BaseModel): """ +class ElementCardValidationVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class ElementCardValidationVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -5286,6 +5830,9 @@ class ElementCardValidationVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[ElementCardValidationVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class ElementCardValidation(BaseModel): """An Inbound Card Validation object. @@ -5425,6 +5972,58 @@ class ElementOther(BaseModel): class Element(BaseModel): + category: Literal[ + "card_authorization", + "card_authentication", + "card_balance_inquiry", + "card_validation", + "card_decline", + "card_reversal", + "card_authorization_expiration", + "card_increment", + "card_settlement", + "card_refund", + "card_fuel_confirmation", + "card_financial", + "other", + ] + """The type of the resource. + + We may add additional possible values for this enum over time; your application + should be able to handle such additions gracefully. + + - `card_authorization` - Card Authorization: details will be under the + `card_authorization` object. + - `card_authentication` - Card Authentication: details will be under the + `card_authentication` object. + - `card_balance_inquiry` - Card Balance Inquiry: details will be under the + `card_balance_inquiry` object. + - `card_validation` - Inbound Card Validation: details will be under the + `card_validation` object. + - `card_decline` - Card Decline: details will be under the `card_decline` + object. + - `card_reversal` - Card Reversal: details will be under the `card_reversal` + object. + - `card_authorization_expiration` - Card Authorization Expiration: details will + be under the `card_authorization_expiration` object. + - `card_increment` - Card Increment: details will be under the `card_increment` + object. + - `card_settlement` - Card Settlement: details will be under the + `card_settlement` object. + - `card_refund` - Card Refund: details will be under the `card_refund` object. + - `card_fuel_confirmation` - Card Fuel Confirmation: details will be under the + `card_fuel_confirmation` object. + - `card_financial` - Card Financial: details will be under the `card_financial` + object. + - `other` - Unknown card payment element. + """ + + created_at: datetime + """ + The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which + the card payment element was created. + """ + card_authentication: Optional[ElementCardAuthentication] = None """A Card Authentication object. @@ -5438,7 +6037,7 @@ class Element(BaseModel): This field will be present in the JSON response if and only if `category` is equal to `card_authorization`. Card Authorizations are temporary holds placed on - a customers funds with the intent to later clear a transaction. + a customer's funds with the intent to later clear a transaction. """ card_authorization_expiration: Optional[ElementCardAuthorizationExpiration] = None @@ -5470,7 +6069,7 @@ class Element(BaseModel): This field will be present in the JSON response if and only if `category` is equal to `card_financial`. Card Financials are temporary holds placed on a - customers funds with the intent to later clear a transaction. + customer's funds with the intent to later clear a transaction. """ card_fuel_confirmation: Optional[ElementCardFuelConfirmation] = None @@ -5494,7 +6093,7 @@ class Element(BaseModel): This field will be present in the JSON response if and only if `category` is equal to `card_refund`. Card Refunds move money back to the cardholder. While - they are usually connected to a Card Settlement an acquirer can also refund + they are usually connected to a Card Settlement, an acquirer can also refund money directly to a card without relation to a transaction. """ @@ -5524,62 +6123,162 @@ class Element(BaseModel): Verification Value are valid. """ - category: Literal[ - "card_authorization", - "card_authentication", - "card_balance_inquiry", - "card_validation", - "card_decline", - "card_reversal", - "card_authorization_expiration", - "card_increment", - "card_settlement", - "card_refund", - "card_fuel_confirmation", - "card_financial", - "other", - ] - """The type of the resource. + other: Optional[ElementOther] = None + """ + If the category of this Transaction source is equal to `other`, this field will + contain an empty object, otherwise it will contain null. + """ - We may add additional possible values for this enum over time; your application - should be able to handle such additions gracefully. - - `card_authorization` - Card Authorization: details will be under the - `card_authorization` object. - - `card_authentication` - Card Authentication: details will be under the - `card_authentication` object. - - `card_balance_inquiry` - Card Balance Inquiry: details will be under the - `card_balance_inquiry` object. - - `card_validation` - Inbound Card Validation: details will be under the - `card_validation` object. - - `card_decline` - Card Decline: details will be under the `card_decline` - object. - - `card_reversal` - Card Reversal: details will be under the `card_reversal` - object. - - `card_authorization_expiration` - Card Authorization Expiration: details will - be under the `card_authorization_expiration` object. - - `card_increment` - Card Increment: details will be under the `card_increment` - object. - - `card_settlement` - Card Settlement: details will be under the - `card_settlement` object. - - `card_refund` - Card Refund: details will be under the `card_refund` object. - - `card_fuel_confirmation` - Card Fuel Confirmation: details will be under the - `card_fuel_confirmation` object. - - `card_financial` - Card Financial: details will be under the `card_financial` - object. - - `other` - Unknown card payment element. - """ +class SchemeFee(BaseModel): + amount: str + """The fee amount given as a string containing a decimal number.""" created_at: datetime """ - The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which - the card payment element was created. + The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) time at which the fee was + created. """ - other: Optional[ElementOther] = None + currency: Literal["USD"] """ - If the category of this Transaction source is equal to `other`, this field will - contain an empty object, otherwise it will contain null. + The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the fee + reimbursement. + + - `USD` - US Dollar (USD) + """ + + fee_type: Literal[ + "visa_international_service_assessment_single_currency", + "visa_international_service_assessment_cross_currency", + "visa_authorization_domestic_point_of_sale", + "visa_authorization_international_point_of_sale", + "visa_authorization_canada_point_of_sale", + "visa_authorization_reversal_point_of_sale", + "visa_authorization_reversal_international_point_of_sale", + "visa_authorization_address_verification_service", + "visa_advanced_authorization", + "visa_message_transmission", + "visa_account_verification_domestic", + "visa_account_verification_international", + "visa_account_verification_canada", + "visa_corporate_acceptance_fee", + "visa_consumer_debit_acceptance_fee", + "visa_business_debit_acceptance_fee", + "visa_purchasing_acceptance_fee", + "visa_purchase_domestic", + "visa_purchase_international", + "visa_credit_purchase_token", + "visa_debit_purchase_token", + "visa_clearing_transmission", + "visa_direct_authorization", + "visa_direct_transaction_domestic", + "visa_service_commercial_credit", + "visa_advertising_service_commercial_credit", + "visa_community_growth_acceleration_program", + "visa_processing_guarantee_commercial_credit", + "pulse_switch_fee", + ] + """The type of fee being assessed. + + - `visa_international_service_assessment_single_currency` - International + Service Assessment (ISA) single-currency is a fee assessed by the card network + for cross-border transactions presented and settled in the same currency. + - `visa_international_service_assessment_cross_currency` - International Service + Assessment (ISA) cross-currency is a fee assessed by the card network for + cross-border transactions presented and settled in different currencies. + - `visa_authorization_domestic_point_of_sale` - Activity and charges for Visa + Settlement System processing for POS (Point-Of-Sale) authorization + transactions. Authorization is the process of approving or declining the + transaction amount specified. The fee is assessed to the Issuer. + - `visa_authorization_international_point_of_sale` - Activity and charges for + Visa Settlement System processing for POS (Point-Of-Sale) International + authorization transactions. Authorization is the process of approving or + declining the transaction amount specified. The fee is assessed to the Issuer. + - `visa_authorization_canada_point_of_sale` - Activity and charges for Visa + Settlement System processing for Canada Region POS (Point-of-Sale) + authorization transactions. Authorization is the process of approving or + declining the transaction amount specified. + - `visa_authorization_reversal_point_of_sale` - Activity only for Visa + Settlement System authorization processing of POS (Point-Of-Sale) reversal + transactions. Authorization reversal represents a VSS message that undoes the + complete or partial actions of a previous authorization request. + - `visa_authorization_reversal_international_point_of_sale` - Activity only for + Visa Settlement System authorization processing of POS (Point-Of-Sale) + International reversal transactions. Authorization reversal represents a VSS + message that undoes the complete or partial actions of a previous + authorization request. + - `visa_authorization_address_verification_service` - A per Address Verification + Service (AVS) result fee. Applies to all usable AVS result codes. + - `visa_advanced_authorization` - Advanced Authorization is a fraud detection + tool that monitors and risk evaluates 100 percent of US VisaNet authorizations + in real-time. Activity related to Purchase (includes Signature Authenticated + Visa and PIN Authenticated Visa Debit (PAVD) transactions). + - `visa_message_transmission` - Issuer Transactions Visa represents a charge + based on total actual monthly processing (Visa transactions only) through a + VisaNet Access Point (VAP). Charges are assessed to the processor for each + VisaNet Access Point. + - `visa_account_verification_domestic` - Activity, per inquiry, related to the + domestic Issuer for Account Number Verification. + - `visa_account_verification_international` - Activity, per inquiry, related to + the international Issuer for Account Number Verification. + - `visa_account_verification_canada` - Activity, per inquiry, related to the + US-Canada Issuer for Account Number Verification. + - `visa_corporate_acceptance_fee` - The Corporate Acceptance Fee is charged to + issuers and is based on the monthly sales volume on Commercial and Government + Debit, Prepaid, Credit, Charge, or Deferred Debit card transactions. + - `visa_consumer_debit_acceptance_fee` - The Consumer Debit Acceptance Fee is + charged to issuers and is based on the monthly sales volume of Consumer Debit + or Prepaid card transactions. The cashback portion of a Debit and Prepaid card + transaction is excluded from the sales volume calculation. + - `visa_business_debit_acceptance_fee` - The Business Acceptance Fee is charged + to issuers and is based on the monthly sales volume on Business Debit, + Prepaid, Credit, Charge, or Deferred Debit card transactions. The cashback + portion is included in the sales volume calculation with the exception of a + Debit and Prepaid card transactions. + - `visa_purchasing_acceptance_fee` - The Purchasing Card Acceptance Fee is + charged to issuers and is based on the monthly sales volume on Commercial and + Government Debit, Prepaid, Credit, Charge, or Deferred Debit card + transactions. + - `visa_purchase_domestic` - Activity and fees for the processing of a sales + draft original for a purchase transaction. + - `visa_purchase_international` - Activity and fees for the processing of an + international sales draft original for a purchase transaction. + - `visa_credit_purchase_token` - Apple Pay Credit Product Token Purchase + Original Transactions. This fee is billed by Visa on behalf of Apple Inc. for + Apple Pay transactions. + - `visa_debit_purchase_token` - Apple Pay Debit Product Token Purchase Original + Transactions. This fee is billed by Visa on behalf of Apple Inc. for Apple Pay + transactions. + - `visa_clearing_transmission` - A per transaction fee assessed for Base II + financial draft - Issuer. + - `visa_direct_authorization` - Issuer charge for Non-Financial OCT/AFT + Authorization 0100 and Declined Financial OCT/AFT 0200 transactions. + - `visa_direct_transaction_domestic` - Data processing charge for Visa Direct + OCTs for all business application identifiers (BAIs) other than money + transfer-bank initiated (BI). BASE II transactions. + - `visa_service_commercial_credit` - Issuer card service fee for Commercial + Credit cards. + - `visa_advertising_service_commercial_credit` - Issuer Advertising Service Fee + for Commercial Credit cards. + - `visa_community_growth_acceleration_program` - Issuer Community Growth + Acceleration Program Fee. + - `visa_processing_guarantee_commercial_credit` - Issuer Processing Guarantee + for Commercial Credit cards. + - `pulse_switch_fee` - Pulse Switch Fee is a fee charged by the Pulse network + for processing transactions on its network. + """ + + fixed_component: Optional[str] = None + """ + The fixed component of the fee, if applicable, given in major units of the fee + amount. + """ + + variable_rate: Optional[str] = None + """ + The variable rate component of the fee, if applicable, given as a decimal (e.g., + 0.015 for 1.5%). """ @@ -5658,6 +6357,9 @@ class CardPayment(BaseModel): physical_card_id: Optional[str] = None """The Physical Card identifier for this payment.""" + scheme_fees: List[SchemeFee] + """The scheme fees associated with this card payment.""" + state: State """The summarized state of this card payment.""" diff --git a/src/increase/types/card_push_transfer.py b/src/increase/types/card_push_transfer.py index f4965f0ae..2f4c3343b 100644 --- a/src/increase/types/card_push_transfer.py +++ b/src/increase/types/card_push_transfer.py @@ -112,9 +112,6 @@ class CreatedByUser(BaseModel): class CreatedBy(BaseModel): """What object created the transfer, either via the API or the dashboard.""" - api_key: Optional[CreatedByAPIKey] = None - """If present, details about the API key that created the transfer.""" - category: Literal["api_key", "oauth_application", "user"] """The type of object that created this transfer. @@ -125,6 +122,9 @@ class CreatedBy(BaseModel): object. """ + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + oauth_application: Optional[CreatedByOAuthApplication] = None """If present, details about the OAuth Application that created the transfer.""" @@ -624,7 +624,7 @@ class Submission(BaseModel): submitted_at: datetime """ The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which - the transfer was submitted to card network. + the transfer was submitted to the card network. """ trace_number: str diff --git a/src/increase/types/card_validation.py b/src/increase/types/card_validation.py index 3d8f45370..8c27a071f 100644 --- a/src/increase/types/card_validation.py +++ b/src/increase/types/card_validation.py @@ -122,9 +122,6 @@ class CreatedByUser(BaseModel): class CreatedBy(BaseModel): """What object created the validation, either via the API or the dashboard.""" - api_key: Optional[CreatedByAPIKey] = None - """If present, details about the API key that created the transfer.""" - category: Literal["api_key", "oauth_application", "user"] """The type of object that created this transfer. @@ -135,6 +132,9 @@ class CreatedBy(BaseModel): object. """ + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + oauth_application: Optional[CreatedByOAuthApplication] = None """If present, details about the OAuth Application that created the transfer.""" diff --git a/src/increase/types/check_deposit.py b/src/increase/types/check_deposit.py index 4b84fa963..5cbddc221 100644 --- a/src/increase/types/check_deposit.py +++ b/src/increase/types/check_deposit.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, Optional +from typing import TYPE_CHECKING, Dict, List, Optional from datetime import datetime from typing_extensions import Literal @@ -11,6 +11,7 @@ __all__ = [ "CheckDeposit", "DepositAcceptance", + "DepositAdjustment", "DepositRejection", "DepositReturn", "DepositSubmission", @@ -78,6 +79,32 @@ def __getattr__(self, attr: str) -> object: ... __pydantic_extra__: Dict[str, object] +class DepositAdjustment(BaseModel): + adjusted_at: datetime + """The time at which the adjustment was received.""" + + amount: int + """The amount of the adjustment.""" + + reason: Literal["late_return", "wrong_payee_credit", "adjusted_amount", "non_conforming_item", "paid"] + """The reason for the adjustment. + + - `late_return` - The return was initiated too late and the receiving + institution has responded with a Late Return Claim. + - `wrong_payee_credit` - The check was deposited to the wrong payee and the + depositing institution has reimbursed the funds with a Wrong Payee Credit. + - `adjusted_amount` - The check was deposited with a different amount than what + was written on the check. + - `non_conforming_item` - The recipient was not able to process the check. This + usually happens for e.g., low quality images. + - `paid` - The check has already been deposited elsewhere and so this is a + duplicate. + """ + + transaction_id: str + """The id of the transaction for the adjustment.""" + + class DepositRejection(BaseModel): """ If your deposit is rejected by Increase, this will contain details as to why it was rejected. @@ -114,6 +141,7 @@ class DepositRejection(BaseModel): "suspected_fraud", "deposit_window_expired", "requested_by_user", + "international", "unknown", ] """Why the check deposit was rejected. @@ -131,6 +159,8 @@ class DepositRejection(BaseModel): - `suspected_fraud` - This check is suspected to be fraudulent. - `deposit_window_expired` - This check's deposit window has expired. - `requested_by_user` - The check was rejected at the user's request. + - `international` - The check is not a U.S. domestic check and cannot be + processed. - `unknown` - The check was rejected for an unknown reason. """ @@ -392,6 +422,12 @@ class CheckDeposit(BaseModel): contain details of the parsed check. """ + deposit_adjustments: List[DepositAdjustment] + """ + If the deposit or the return was adjusted by the receiving institution, this + will contain details of the adjustments. + """ + deposit_rejection: Optional[DepositRejection] = None """ If your deposit is rejected by Increase, this will contain details as to why it diff --git a/src/increase/types/check_transfer.py b/src/increase/types/check_transfer.py index 8a192cfb2..de76a0375 100644 --- a/src/increase/types/check_transfer.py +++ b/src/increase/types/check_transfer.py @@ -89,9 +89,6 @@ class CreatedByUser(BaseModel): class CreatedBy(BaseModel): """What object created the transfer, either via the API or the dashboard.""" - api_key: Optional[CreatedByAPIKey] = None - """If present, details about the API key that created the transfer.""" - category: Literal["api_key", "oauth_application", "user"] """The type of object that created this transfer. @@ -102,6 +99,9 @@ class CreatedBy(BaseModel): object. """ + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + oauth_application: Optional[CreatedByOAuthApplication] = None """If present, details about the OAuth Application that created the transfer.""" @@ -114,20 +114,23 @@ class Mailing(BaseModel): If the check has been mailed by Increase, this will contain details of the shipment. """ - image_id: Optional[str] = None - """ - The ID of the file corresponding to an image of the check that was mailed, if - available. - """ - mailed_at: datetime """ The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which the check was mailed. """ - tracking_number: Optional[str] = None - """The tracking number of the shipment, if available for the shipping method.""" + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] class PhysicalCheckMailingAddress(BaseModel): @@ -349,19 +352,10 @@ class SubmissionSubmittedAddress(BaseModel): class Submission(BaseModel): """After the transfer is submitted, this will contain supplemental details.""" - address_correction_action: Literal["none", "standardization", "standardization_with_address_change", "error"] + preview_file_id: Optional[str] = None """ - Per USPS requirements, Increase will standardize the address to USPS standards - and check it against the USPS National Change of Address (NCOA) database before - mailing it. This indicates what modifications, if any, were made to the address - before printing and mailing the check. - - - `none` - No address correction took place. - - `standardization` - The address was standardized. - - `standardization_with_address_change` - The address was first standardized and - then changed because the recipient moved. - - `error` - An error occurred while correcting the address. This typically means - the USPS could not find that address. The address was not changed. + The ID of the file corresponding to an image of the check that was mailed, if + available. """ submitted_address: SubmissionSubmittedAddress @@ -371,7 +365,10 @@ class Submission(BaseModel): """ submitted_at: datetime - """When this check transfer was submitted to our check printer.""" + """When this check was submitted to our check printer.""" + + tracking_number: Optional[str] = None + """The tracking number for the check shipment.""" if TYPE_CHECKING: # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a diff --git a/src/increase/types/check_transfer_create_params.py b/src/increase/types/check_transfer_create_params.py index a93f1da43..e812775d2 100644 --- a/src/increase/types/check_transfer_create_params.py +++ b/src/increase/types/check_transfer_create_params.py @@ -2,9 +2,9 @@ from __future__ import annotations -from typing import Dict, Union, Iterable +from typing import Union, Iterable from datetime import date -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from .._utils import PropertyInfo @@ -156,7 +156,7 @@ class PhysicalCheckReturnAddress(TypedDict, total=False): """ -class PhysicalCheckTyped(TypedDict, total=False): +class PhysicalCheck(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """Details relating to the physical check that Increase will print and mail. This is required if `fulfillment_method` is equal to `physical_check`. It must not be included if any other `fulfillment_method` is provided. @@ -222,10 +222,7 @@ class PhysicalCheckTyped(TypedDict, total=False): """ -PhysicalCheck: TypeAlias = Union[PhysicalCheckTyped, Dict[str, object]] - - -class ThirdPartyTyped(TypedDict, total=False): +class ThirdParty(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """Details relating to the custom fulfillment you will perform. This is required if `fulfillment_method` is equal to `third_party`. It must not be included if any other `fulfillment_method` is provided. @@ -238,6 +235,3 @@ class ThirdPartyTyped(TypedDict, total=False): this is omitted, Increase will be unable to validate the payer name when the check is deposited. """ - - -ThirdParty: TypeAlias = Union[ThirdPartyTyped, Dict[str, object]] diff --git a/src/increase/types/declined_transaction.py b/src/increase/types/declined_transaction.py index e37adcfa9..3652619a3 100644 --- a/src/increase/types/declined_transaction.py +++ b/src/increase/types/declined_transaction.py @@ -31,6 +31,7 @@ "SourceCardDeclineVerification", "SourceCardDeclineVerificationCardVerificationCode", "SourceCardDeclineVerificationCardholderAddress", + "SourceCardDeclineVerificationCardholderName", "SourceCheckDecline", "SourceCheckDepositRejection", "SourceInboundFednowTransferDecline", @@ -448,6 +449,7 @@ class SourceCardDeclineNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -462,8 +464,10 @@ class SourceCardDeclineNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -479,6 +483,41 @@ class SourceCardDeclineNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class SourceCardDeclineNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -584,6 +623,19 @@ class SourceCardDeclineVerificationCardholderAddress(BaseModel): """ +class SourceCardDeclineVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class SourceCardDeclineVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -599,6 +651,9 @@ class SourceCardDeclineVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[SourceCardDeclineVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class SourceCardDecline(BaseModel): """A Card Decline object. @@ -821,6 +876,7 @@ class SourceCardDecline(BaseModel): "declined_by_stand_in_processing", "invalid_physical_card", "missing_original_authorization", + "invalid_cryptogram", "failed_3ds_authentication", "suspected_card_testing", "suspected_fraud", @@ -846,10 +902,12 @@ class SourceCardDecline(BaseModel): - `webhook_timed_out` - Your application webhook did not respond without the required timeout. - `declined_by_stand_in_processing` - Declined by stand-in processing. - - `invalid_physical_card` - The card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The card read had an invalid CVV or dCVV. - `missing_original_authorization` - The original card authorization for this incremental authorization does not exist. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `failed_3ds_authentication` - The transaction was declined because the 3DS authentication failed. - `suspected_card_testing` - The transaction was suspected to be used by a card @@ -1012,6 +1070,7 @@ class SourceCheckDepositRejection(BaseModel): "suspected_fraud", "deposit_window_expired", "requested_by_user", + "international", "unknown", ] """Why the check deposit was rejected. @@ -1029,6 +1088,8 @@ class SourceCheckDepositRejection(BaseModel): - `suspected_fraud` - This check is suspected to be fraudulent. - `deposit_window_expired` - This check's deposit window has expired. - `requested_by_user` - The check was rejected at the user's request. + - `international` - The check is not a U.S. domestic check and cannot be + processed. - `unknown` - The check was rejected for an unknown reason. """ @@ -1208,20 +1269,6 @@ class Source(BaseModel): This is an object giving more details on the network-level event that caused the Declined Transaction. For example, for a card transaction this lists the merchant's industry and location. Note that for backwards compatibility reasons, additional undocumented keys may appear in this object. These should be treated as deprecated and will be removed in the future. """ - ach_decline: Optional[SourceACHDecline] = None - """An ACH Decline object. - - This field will be present in the JSON response if and only if `category` is - equal to `ach_decline`. - """ - - card_decline: Optional[SourceCardDecline] = None - """A Card Decline object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_decline`. - """ - category: Literal[ "ach_decline", "card_decline", @@ -1255,6 +1302,20 @@ class Source(BaseModel): reason. """ + ach_decline: Optional[SourceACHDecline] = None + """An ACH Decline object. + + This field will be present in the JSON response if and only if `category` is + equal to `ach_decline`. + """ + + card_decline: Optional[SourceCardDecline] = None + """A Card Decline object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_decline`. + """ + check_decline: Optional[SourceCheckDecline] = None """A Check Decline object. diff --git a/src/increase/types/digital_card_profile.py b/src/increase/types/digital_card_profile.py index 9c5a9a596..347f9a6a2 100644 --- a/src/increase/types/digital_card_profile.py +++ b/src/increase/types/digital_card_profile.py @@ -1,9 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import TYPE_CHECKING, Dict, Optional from datetime import datetime from typing_extensions import Literal +from pydantic import Field as FieldInfo + from .._models import BaseModel __all__ = ["DigitalCardProfile", "TextColor"] @@ -51,7 +53,7 @@ class DigitalCardProfile(BaseModel): created_at: datetime """ The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which - the Card Dispute was created. + the Digital Card Profile was created. """ description: str @@ -86,3 +88,15 @@ class DigitalCardProfile(BaseModel): For this resource it will always be `digital_card_profile`. """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/digital_wallet_token.py b/src/increase/types/digital_wallet_token.py index 7fd051f3d..83fb5ed2f 100644 --- a/src/increase/types/digital_wallet_token.py +++ b/src/increase/types/digital_wallet_token.py @@ -6,7 +6,7 @@ from .._models import BaseModel -__all__ = ["DigitalWalletToken", "Cardholder", "Device", "Update"] +__all__ = ["DigitalWalletToken", "Cardholder", "Device", "DynamicPrimaryAccountNumber", "Update"] class Cardholder(BaseModel): @@ -55,6 +55,16 @@ class Device(BaseModel): """Name of the device, for example "My Work Phone".""" +class DynamicPrimaryAccountNumber(BaseModel): + """The redacted Dynamic Primary Account Number.""" + + first6: str + """The first 6 digits of the token's Dynamic Primary Account Number.""" + + last4: str + """The last 4 digits of the token's Dynamic Primary Account Number.""" + + class Update(BaseModel): status: Literal["active", "inactive", "suspended", "deactivated"] """The status the update changed this Digital Wallet Token to. @@ -96,6 +106,9 @@ class DigitalWalletToken(BaseModel): device: Device """The device that was used to create the Digital Wallet Token.""" + dynamic_primary_account_number: Optional[DynamicPrimaryAccountNumber] = None + """The redacted Dynamic Primary Account Number.""" + status: Literal["active", "inactive", "suspended", "deactivated"] """This indicates if payments can be made with the Digital Wallet Token. diff --git a/src/increase/types/entity.py b/src/increase/types/entity.py index 3670d6329..4d4ff37db 100644 --- a/src/increase/types/entity.py +++ b/src/increase/types/entity.py @@ -141,7 +141,7 @@ class CorporationBeneficialOwnerIndividual(BaseModel): class CorporationBeneficialOwner(BaseModel): - beneficial_owner_id: str + id: str """The identifier of this beneficial owner.""" company_title: Optional[str] = None @@ -150,14 +150,20 @@ class CorporationBeneficialOwner(BaseModel): individual: CorporationBeneficialOwnerIndividual """Personal details for the beneficial owner.""" - prong: Literal["ownership", "control"] - """Why this person is considered a beneficial owner of the entity. + prongs: List[Literal["ownership", "control"]] + """Why this person is considered a beneficial owner of the entity.""" - - `ownership` - A person with 25% or greater direct or indirect ownership of the - entity. - - `control` - A person who manages, directs, or has significant control of the - entity. - """ + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] class Corporation(BaseModel): @@ -463,13 +469,14 @@ class ThirdPartyVerification(BaseModel): reference: str """The reference identifier for the third party verification.""" - vendor: Literal["alloy", "middesk", "oscilar", "persona"] + vendor: Literal["alloy", "middesk", "oscilar", "persona", "taktile"] """The vendor that was used to perform the verification. - `alloy` - Alloy. See https://alloy.com for more information. - `middesk` - Middesk. See https://middesk.com for more information. - `oscilar` - Oscilar. See https://oscilar.com for more information. - `persona` - Persona. See https://withpersona.com for more information. + - `taktile` - Taktile. See https://taktile.com for more information. """ @@ -810,3 +817,15 @@ class Entity(BaseModel): For this resource it will always be `entity`. """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/entity_confirm_params.py b/src/increase/types/entity_confirm_params.py deleted file mode 100644 index cf9a0dfc8..000000000 --- a/src/increase/types/entity_confirm_params.py +++ /dev/null @@ -1,19 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Union -from datetime import datetime -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["EntityConfirmParams"] - - -class EntityConfirmParams(TypedDict, total=False): - confirmed_at: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] - """When your user confirmed the Entity's details. - - If not provided, the current time will be used. - """ diff --git a/src/increase/types/entity_create_beneficial_owner_params.py b/src/increase/types/entity_create_beneficial_owner_params.py index 627979061..e3091081e 100644 --- a/src/increase/types/entity_create_beneficial_owner_params.py +++ b/src/increase/types/entity_create_beneficial_owner_params.py @@ -2,9 +2,9 @@ from __future__ import annotations -from typing import Dict, List, Union +from typing import List, Union from datetime import date -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from .._utils import PropertyInfo @@ -122,7 +122,7 @@ class BeneficialOwnerIndividualIdentificationPassport(TypedDict, total=False): """The identifier of the File containing the passport.""" -class BeneficialOwnerIndividualIdentificationTyped(TypedDict, total=False): +class BeneficialOwnerIndividualIdentification(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """A means of verifying the person's identity.""" method: Required[ @@ -169,11 +169,6 @@ class BeneficialOwnerIndividualIdentificationTyped(TypedDict, total=False): """ -BeneficialOwnerIndividualIdentification: TypeAlias = Union[ - BeneficialOwnerIndividualIdentificationTyped, Dict[str, object] -] - - class BeneficialOwnerIndividual(TypedDict, total=False): """Personal details for the beneficial owner.""" @@ -201,7 +196,7 @@ class BeneficialOwnerIndividual(TypedDict, total=False): """ -class BeneficialOwnerTyped(TypedDict, total=False): +class BeneficialOwner(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """ The identifying details of anyone controlling or owning 25% or more of the corporation. """ @@ -218,6 +213,3 @@ class BeneficialOwnerTyped(TypedDict, total=False): company_title: str """This person's role or title within the entity.""" - - -BeneficialOwner: TypeAlias = Union[BeneficialOwnerTyped, Dict[str, object]] diff --git a/src/increase/types/entity_create_params.py b/src/increase/types/entity_create_params.py index df2c33a90..a8f9bb97e 100644 --- a/src/increase/types/entity_create_params.py +++ b/src/increase/types/entity_create_params.py @@ -2,9 +2,9 @@ from __future__ import annotations -from typing import Dict, List, Union, Iterable +from typing import List, Union, Iterable from datetime import date, datetime -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from .._utils import PropertyInfo @@ -99,7 +99,7 @@ class EntityCreateParams(TypedDict, total=False): risk_rating: RiskRating """ - An assessment of the entity’s potential risk of involvement in financial crimes, + An assessment of the entity's potential risk of involvement in financial crimes, such as money laundering. """ @@ -245,7 +245,7 @@ class CorporationBeneficialOwnerIndividualIdentificationPassport(TypedDict, tota """The identifier of the File containing the passport.""" -class CorporationBeneficialOwnerIndividualIdentificationTyped(TypedDict, total=False): +class CorporationBeneficialOwnerIndividualIdentification(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """A means of verifying the person's identity.""" method: Required[ @@ -292,11 +292,6 @@ class CorporationBeneficialOwnerIndividualIdentificationTyped(TypedDict, total=F """ -CorporationBeneficialOwnerIndividualIdentification: TypeAlias = Union[ - CorporationBeneficialOwnerIndividualIdentificationTyped, Dict[str, object] -] - - class CorporationBeneficialOwnerIndividual(TypedDict, total=False): """Personal details for the beneficial owner.""" @@ -324,7 +319,7 @@ class CorporationBeneficialOwnerIndividual(TypedDict, total=False): """ -class CorporationBeneficialOwnerTyped(TypedDict, total=False): +class CorporationBeneficialOwner(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] individual: Required[CorporationBeneficialOwnerIndividual] """Personal details for the beneficial owner.""" @@ -339,9 +334,6 @@ class CorporationBeneficialOwnerTyped(TypedDict, total=False): """This person's role or title within the entity.""" -CorporationBeneficialOwner: TypeAlias = Union[CorporationBeneficialOwnerTyped, Dict[str, object]] - - class Corporation(TypedDict, total=False): """Details of the corporation entity to create. @@ -563,7 +555,7 @@ class JointIndividualIdentificationPassport(TypedDict, total=False): """The identifier of the File containing the passport.""" -class JointIndividualIdentificationTyped(TypedDict, total=False): +class JointIndividualIdentification(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """A means of verifying the person's identity.""" method: Required[ @@ -610,9 +602,6 @@ class JointIndividualIdentificationTyped(TypedDict, total=False): """ -JointIndividualIdentification: TypeAlias = Union[JointIndividualIdentificationTyped, Dict[str, object]] - - class JointIndividual(TypedDict, total=False): address: Required[JointIndividualAddress] """The individual's physical address. @@ -739,7 +728,7 @@ class NaturalPersonIdentificationPassport(TypedDict, total=False): """The identifier of the File containing the passport.""" -class NaturalPersonIdentificationTyped(TypedDict, total=False): +class NaturalPersonIdentification(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """A means of verifying the person's identity.""" method: Required[ @@ -786,9 +775,6 @@ class NaturalPersonIdentificationTyped(TypedDict, total=False): """ -NaturalPersonIdentification: TypeAlias = Union[NaturalPersonIdentificationTyped, Dict[str, object]] - - class NaturalPerson(TypedDict, total=False): """Details of the natural person entity to create. @@ -821,7 +807,7 @@ class NaturalPerson(TypedDict, total=False): class RiskRating(TypedDict, total=False): """ - An assessment of the entity’s potential risk of involvement in financial crimes, such as money laundering. + An assessment of the entity's potential risk of involvement in financial crimes, such as money laundering. """ rated_at: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] @@ -866,13 +852,14 @@ class ThirdPartyVerification(TypedDict, total=False): reference: Required[str] """The reference identifier for the third party verification.""" - vendor: Required[Literal["alloy", "middesk", "oscilar", "persona"]] + vendor: Required[Literal["alloy", "middesk", "oscilar", "persona", "taktile"]] """The vendor that was used to perform the verification. - `alloy` - Alloy. See https://alloy.com for more information. - `middesk` - Middesk. See https://middesk.com for more information. - `oscilar` - Oscilar. See https://oscilar.com for more information. - `persona` - Persona. See https://withpersona.com for more information. + - `taktile` - Taktile. See https://taktile.com for more information. """ @@ -992,7 +979,7 @@ class TrustTrusteeIndividualIdentificationPassport(TypedDict, total=False): """The identifier of the File containing the passport.""" -class TrustTrusteeIndividualIdentificationTyped(TypedDict, total=False): +class TrustTrusteeIndividualIdentification(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """A means of verifying the person's identity.""" method: Required[ @@ -1039,9 +1026,6 @@ class TrustTrusteeIndividualIdentificationTyped(TypedDict, total=False): """ -TrustTrusteeIndividualIdentification: TypeAlias = Union[TrustTrusteeIndividualIdentificationTyped, Dict[str, object]] - - class TrustTrusteeIndividual(TypedDict, total=False): """Details of the individual trustee. @@ -1178,7 +1162,7 @@ class TrustGrantorIdentificationPassport(TypedDict, total=False): """The identifier of the File containing the passport.""" -class TrustGrantorIdentificationTyped(TypedDict, total=False): +class TrustGrantorIdentification(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """A means of verifying the person's identity.""" method: Required[ @@ -1225,9 +1209,6 @@ class TrustGrantorIdentificationTyped(TypedDict, total=False): """ -TrustGrantorIdentification: TypeAlias = Union[TrustGrantorIdentificationTyped, Dict[str, object]] - - class TrustGrantor(TypedDict, total=False): """The grantor of the trust. Required if `category` is equal to `revocable`.""" diff --git a/src/increase/types/entity_update_address_params.py b/src/increase/types/entity_update_address_params.py deleted file mode 100644 index c5fac648b..000000000 --- a/src/increase/types/entity_update_address_params.py +++ /dev/null @@ -1,40 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -__all__ = ["EntityUpdateAddressParams", "Address"] - - -class EntityUpdateAddressParams(TypedDict, total=False): - address: Required[Address] - """The entity's physical address. - - Mail receiving locations like PO Boxes and PMB's are disallowed. - """ - - -class Address(TypedDict, total=False): - """The entity's physical address. - - Mail receiving locations like PO Boxes and PMB's are disallowed. - """ - - city: Required[str] - """The city of the address.""" - - line1: Required[str] - """The first line of the address. This is usually the street number and street.""" - - state: Required[str] - """ - The two-letter United States Postal Service (USPS) abbreviation for the state of - the address. - """ - - zip: Required[str] - """The ZIP code of the address.""" - - line2: str - """The second line of the address. This might be the floor or room number.""" diff --git a/src/increase/types/entity_update_industry_code_params.py b/src/increase/types/entity_update_industry_code_params.py deleted file mode 100644 index 7843d7137..000000000 --- a/src/increase/types/entity_update_industry_code_params.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -__all__ = ["EntityUpdateIndustryCodeParams"] - - -class EntityUpdateIndustryCodeParams(TypedDict, total=False): - industry_code: Required[str] - """ - The North American Industry Classification System (NAICS) code for the - corporation's primary line of business. This is a number, like `5132` for - `Software Publishers`. A full list of classification codes is available - [here](https://increase.com/documentation/data-dictionary#north-american-industry-classification-system-codes). - """ diff --git a/src/increase/types/entity_update_params.py b/src/increase/types/entity_update_params.py index 8c09fb431..38ebb27f8 100644 --- a/src/increase/types/entity_update_params.py +++ b/src/increase/types/entity_update_params.py @@ -133,6 +133,9 @@ class Corporation(TypedDict, total=False): name: str """The legal name of the corporation.""" + tax_identifier: str + """The Employer Identification Number (EIN) for the corporation.""" + class GovernmentAuthorityAddress(TypedDict, total=False): """The entity's physical address. @@ -244,13 +247,14 @@ class ThirdPartyVerification(TypedDict, total=False): reference: Required[str] """The reference identifier for the third party verification.""" - vendor: Required[Literal["alloy", "middesk", "oscilar", "persona"]] + vendor: Required[Literal["alloy", "middesk", "oscilar", "persona", "taktile"]] """The vendor that was used to perform the verification. - `alloy` - Alloy. See https://alloy.com for more information. - `middesk` - Middesk. See https://middesk.com for more information. - `oscilar` - Oscilar. See https://oscilar.com for more information. - `persona` - Persona. See https://withpersona.com for more information. + - `taktile` - Taktile. See https://taktile.com for more information. """ diff --git a/src/increase/types/event.py b/src/increase/types/event.py index 906307e02..4e1ae34b6 100644 --- a/src/increase/types/event.py +++ b/src/increase/types/event.py @@ -35,6 +35,12 @@ class Event(BaseModel): "ach_prenotification.updated", "ach_transfer.created", "ach_transfer.updated", + "blockchain_address.created", + "blockchain_address.updated", + "blockchain_offramp_transfer.created", + "blockchain_offramp_transfer.updated", + "blockchain_onramp_transfer.created", + "blockchain_onramp_transfer.updated", "bookkeeping_account.created", "bookkeeping_account.updated", "bookkeeping_entry_set.updated", @@ -104,6 +110,8 @@ class Event(BaseModel): "physical_card.updated", "physical_card_profile.created", "physical_card_profile.updated", + "physical_check.created", + "physical_check.updated", "program.created", "program.updated", "proof_of_authorization_request.created", @@ -144,6 +152,18 @@ class Event(BaseModel): updated. - `ach_transfer.created` - Occurs whenever an ACH Transfer is created. - `ach_transfer.updated` - Occurs whenever an ACH Transfer is updated. + - `blockchain_address.created` - Occurs whenever a Blockchain Address is + created. + - `blockchain_address.updated` - Occurs whenever a Blockchain Address is + updated. + - `blockchain_offramp_transfer.created` - Occurs whenever a Blockchain Off-Ramp + Transfer is created. + - `blockchain_offramp_transfer.updated` - Occurs whenever a Blockchain Off-Ramp + Transfer is updated. + - `blockchain_onramp_transfer.created` - Occurs whenever a Blockchain On-Ramp + Transfer is created. + - `blockchain_onramp_transfer.updated` - Occurs whenever a Blockchain On-Ramp + Transfer is updated. - `bookkeeping_account.created` - Occurs whenever a Bookkeeping Account is created. - `bookkeeping_account.updated` - Occurs whenever a Bookkeeping Account is @@ -248,6 +268,8 @@ class Event(BaseModel): created. - `physical_card_profile.updated` - Occurs whenever a Physical Card Profile is updated. + - `physical_check.created` - Occurs whenever a Physical Check is created. + - `physical_check.updated` - Occurs whenever a Physical Check is updated. - `program.created` - Occurs whenever a Program is created. - `program.updated` - Occurs whenever a Program is updated. - `proof_of_authorization_request.created` - Occurs whenever a Proof of diff --git a/src/increase/types/event_list_params.py b/src/increase/types/event_list_params.py index d26640c14..bc0e7ba34 100644 --- a/src/increase/types/event_list_params.py +++ b/src/increase/types/event_list_params.py @@ -45,6 +45,12 @@ class EventListParams(TypedDict, total=False): "ach_prenotification.updated", "ach_transfer.created", "ach_transfer.updated", + "blockchain_address.created", + "blockchain_address.updated", + "blockchain_offramp_transfer.created", + "blockchain_offramp_transfer.updated", + "blockchain_onramp_transfer.created", + "blockchain_onramp_transfer.updated", "bookkeeping_account.created", "bookkeeping_account.updated", "bookkeeping_entry_set.updated", @@ -114,6 +120,8 @@ class EventListParams(TypedDict, total=False): "physical_card.updated", "physical_card_profile.created", "physical_card_profile.updated", + "physical_check.created", + "physical_check.updated", "program.created", "program.updated", "proof_of_authorization_request.created", diff --git a/src/increase/types/event_subscription.py b/src/increase/types/event_subscription.py index 488fc5a44..3663f5c4f 100644 --- a/src/increase/types/event_subscription.py +++ b/src/increase/types/event_subscription.py @@ -1,41 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import TYPE_CHECKING, Dict, List, Optional from datetime import datetime from typing_extensions import Literal -from .._models import BaseModel - -__all__ = ["EventSubscription"] - - -class EventSubscription(BaseModel): - """Webhooks are event notifications we send to you by HTTPS POST requests. - - Event Subscriptions are how you configure your application to listen for them. You can create an Event Subscription through your [developer dashboard](https://dashboard.increase.com/developers/webhooks) or the API. For more information, see our [webhooks guide](https://increase.com/documentation/webhooks). - """ +from pydantic import Field as FieldInfo - id: str - """The event subscription identifier.""" +from .._models import BaseModel - created_at: datetime - """The time the event subscription was created.""" +__all__ = ["EventSubscription", "SelectedEventCategory"] - idempotency_key: Optional[str] = None - """The idempotency key you chose for this object. - This value is unique across Increase and is used to ensure that a request is - only processed once. Learn more about - [idempotency](https://increase.com/documentation/idempotency-keys). - """ - - oauth_connection_id: Optional[str] = None - """ - If specified, this subscription will only receive webhooks for Events associated - with this OAuth Connection. - """ - - selected_event_category: Optional[ +class SelectedEventCategory(BaseModel): + event_category: Optional[ Literal[ "account.created", "account.updated", @@ -48,6 +25,12 @@ class EventSubscription(BaseModel): "ach_prenotification.updated", "ach_transfer.created", "ach_transfer.updated", + "blockchain_address.created", + "blockchain_address.updated", + "blockchain_offramp_transfer.created", + "blockchain_offramp_transfer.updated", + "blockchain_onramp_transfer.created", + "blockchain_onramp_transfer.updated", "bookkeeping_account.created", "bookkeeping_account.updated", "bookkeeping_entry_set.updated", @@ -117,6 +100,8 @@ class EventSubscription(BaseModel): "physical_card.updated", "physical_card_profile.created", "physical_card_profile.updated", + "physical_check.created", + "physical_check.updated", "program.created", "program.updated", "proof_of_authorization_request.created", @@ -140,9 +125,7 @@ class EventSubscription(BaseModel): "wire_transfer.updated", ] ] = None - """ - If specified, this subscription will only receive webhooks for Events with the - specified `category`. + """The category of the Event. - `account.created` - Occurs whenever an Account is created. - `account.updated` - Occurs whenever an Account is updated. @@ -157,6 +140,18 @@ class EventSubscription(BaseModel): updated. - `ach_transfer.created` - Occurs whenever an ACH Transfer is created. - `ach_transfer.updated` - Occurs whenever an ACH Transfer is updated. + - `blockchain_address.created` - Occurs whenever a Blockchain Address is + created. + - `blockchain_address.updated` - Occurs whenever a Blockchain Address is + updated. + - `blockchain_offramp_transfer.created` - Occurs whenever a Blockchain Off-Ramp + Transfer is created. + - `blockchain_offramp_transfer.updated` - Occurs whenever a Blockchain Off-Ramp + Transfer is updated. + - `blockchain_onramp_transfer.created` - Occurs whenever a Blockchain On-Ramp + Transfer is created. + - `blockchain_onramp_transfer.updated` - Occurs whenever a Blockchain On-Ramp + Transfer is updated. - `bookkeeping_account.created` - Occurs whenever a Bookkeeping Account is created. - `bookkeeping_account.updated` - Occurs whenever a Bookkeeping Account is @@ -261,6 +256,8 @@ class EventSubscription(BaseModel): created. - `physical_card_profile.updated` - Occurs whenever a Physical Card Profile is updated. + - `physical_check.created` - Occurs whenever a Physical Check is created. + - `physical_check.updated` - Occurs whenever a Physical Check is updated. - `program.created` - Occurs whenever a Program is created. - `program.updated` - Occurs whenever a Program is updated. - `proof_of_authorization_request.created` - Occurs whenever a Proof of @@ -300,6 +297,39 @@ class EventSubscription(BaseModel): - `wire_transfer.updated` - Occurs whenever a Wire Transfer is updated. """ + +class EventSubscription(BaseModel): + """Webhooks are event notifications we send to you by HTTPS POST requests. + + Event Subscriptions are how you configure your application to listen for them. You can create an Event Subscription through your [developer dashboard](https://dashboard.increase.com/developers/webhooks) or the API. For more information, see our [webhooks guide](https://increase.com/documentation/webhooks). + """ + + id: str + """The event subscription identifier.""" + + created_at: datetime + """The time the event subscription was created.""" + + idempotency_key: Optional[str] = None + """The idempotency key you chose for this object. + + This value is unique across Increase and is used to ensure that a request is + only processed once. Learn more about + [idempotency](https://increase.com/documentation/idempotency-keys). + """ + + oauth_connection_id: Optional[str] = None + """ + If specified, this subscription will only receive webhooks for Events associated + with this OAuth Connection. + """ + + selected_event_categories: Optional[List[SelectedEventCategory]] = None + """ + If specified, this subscription will only receive webhooks for Events with the + specified `category`. + """ + status: Literal["active", "disabled", "deleted", "requires_attention"] """This indicates if we'll send notifications to this subscription. @@ -320,3 +350,15 @@ class EventSubscription(BaseModel): url: str """The webhook url where we'll send notifications.""" + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/event_subscription_create_params.py b/src/increase/types/event_subscription_create_params.py index 46a68ffe5..c683d54e3 100644 --- a/src/increase/types/event_subscription_create_params.py +++ b/src/increase/types/event_subscription_create_params.py @@ -2,9 +2,10 @@ from __future__ import annotations +from typing import Iterable from typing_extensions import Literal, Required, TypedDict -__all__ = ["EventSubscriptionCreateParams"] +__all__ = ["EventSubscriptionCreateParams", "SelectedEventCategory"] class EventSubscriptionCreateParams(TypedDict, total=False): @@ -17,112 +18,143 @@ class EventSubscriptionCreateParams(TypedDict, total=False): with the specified OAuth Connection. """ - selected_event_category: Literal[ - "account.created", - "account.updated", - "account_number.created", - "account_number.updated", - "account_statement.created", - "account_transfer.created", - "account_transfer.updated", - "ach_prenotification.created", - "ach_prenotification.updated", - "ach_transfer.created", - "ach_transfer.updated", - "bookkeeping_account.created", - "bookkeeping_account.updated", - "bookkeeping_entry_set.updated", - "card.created", - "card.updated", - "card_payment.created", - "card_payment.updated", - "card_profile.created", - "card_profile.updated", - "card_dispute.created", - "card_dispute.updated", - "check_deposit.created", - "check_deposit.updated", - "check_transfer.created", - "check_transfer.updated", - "declined_transaction.created", - "digital_card_profile.created", - "digital_card_profile.updated", - "digital_wallet_token.created", - "digital_wallet_token.updated", - "document.created", - "entity.created", - "entity.updated", - "event_subscription.created", - "event_subscription.updated", - "export.created", - "export.updated", - "external_account.created", - "external_account.updated", - "fednow_transfer.created", - "fednow_transfer.updated", - "file.created", - "group.updated", - "group.heartbeat", - "inbound_ach_transfer.created", - "inbound_ach_transfer.updated", - "inbound_ach_transfer_return.created", - "inbound_ach_transfer_return.updated", - "inbound_check_deposit.created", - "inbound_check_deposit.updated", - "inbound_fednow_transfer.created", - "inbound_fednow_transfer.updated", - "inbound_mail_item.created", - "inbound_mail_item.updated", - "inbound_real_time_payments_transfer.created", - "inbound_real_time_payments_transfer.updated", - "inbound_wire_drawdown_request.created", - "inbound_wire_transfer.created", - "inbound_wire_transfer.updated", - "intrafi_account_enrollment.created", - "intrafi_account_enrollment.updated", - "intrafi_exclusion.created", - "intrafi_exclusion.updated", - "legacy_card_dispute.created", - "legacy_card_dispute.updated", - "lockbox.created", - "lockbox.updated", - "oauth_connection.created", - "oauth_connection.deactivated", - "card_push_transfer.created", - "card_push_transfer.updated", - "card_validation.created", - "card_validation.updated", - "pending_transaction.created", - "pending_transaction.updated", - "physical_card.created", - "physical_card.updated", - "physical_card_profile.created", - "physical_card_profile.updated", - "program.created", - "program.updated", - "proof_of_authorization_request.created", - "proof_of_authorization_request.updated", - "real_time_decision.card_authorization_requested", - "real_time_decision.card_balance_inquiry_requested", - "real_time_decision.digital_wallet_token_requested", - "real_time_decision.digital_wallet_authentication_requested", - "real_time_decision.card_authentication_requested", - "real_time_decision.card_authentication_challenge_requested", - "real_time_payments_transfer.created", - "real_time_payments_transfer.updated", - "real_time_payments_request_for_payment.created", - "real_time_payments_request_for_payment.updated", - "swift_transfer.created", - "swift_transfer.updated", - "transaction.created", - "wire_drawdown_request.created", - "wire_drawdown_request.updated", - "wire_transfer.created", - "wire_transfer.updated", - ] + selected_event_categories: Iterable[SelectedEventCategory] """ If specified, this subscription will only receive webhooks for Events with the - specified `category`. + specified `category`. If specifying a Real-Time Decision event category, only + one Event Category can be specified for the Event Subscription. + """ + + shared_secret: str + """The key that will be used to sign webhooks. + + If no value is passed, a random string will be used as default. + """ + + status: Literal["active", "disabled"] + """The status of the event subscription. Defaults to `active` if not specified. + + - `active` - The subscription is active and Events will be delivered normally. + - `disabled` - The subscription is temporarily disabled and Events will not be + delivered. + """ + + +class SelectedEventCategory(TypedDict, total=False): + event_category: Required[ + Literal[ + "account.created", + "account.updated", + "account_number.created", + "account_number.updated", + "account_statement.created", + "account_transfer.created", + "account_transfer.updated", + "ach_prenotification.created", + "ach_prenotification.updated", + "ach_transfer.created", + "ach_transfer.updated", + "blockchain_address.created", + "blockchain_address.updated", + "blockchain_offramp_transfer.created", + "blockchain_offramp_transfer.updated", + "blockchain_onramp_transfer.created", + "blockchain_onramp_transfer.updated", + "bookkeeping_account.created", + "bookkeeping_account.updated", + "bookkeeping_entry_set.updated", + "card.created", + "card.updated", + "card_payment.created", + "card_payment.updated", + "card_profile.created", + "card_profile.updated", + "card_dispute.created", + "card_dispute.updated", + "check_deposit.created", + "check_deposit.updated", + "check_transfer.created", + "check_transfer.updated", + "declined_transaction.created", + "digital_card_profile.created", + "digital_card_profile.updated", + "digital_wallet_token.created", + "digital_wallet_token.updated", + "document.created", + "entity.created", + "entity.updated", + "event_subscription.created", + "event_subscription.updated", + "export.created", + "export.updated", + "external_account.created", + "external_account.updated", + "fednow_transfer.created", + "fednow_transfer.updated", + "file.created", + "group.updated", + "group.heartbeat", + "inbound_ach_transfer.created", + "inbound_ach_transfer.updated", + "inbound_ach_transfer_return.created", + "inbound_ach_transfer_return.updated", + "inbound_check_deposit.created", + "inbound_check_deposit.updated", + "inbound_fednow_transfer.created", + "inbound_fednow_transfer.updated", + "inbound_mail_item.created", + "inbound_mail_item.updated", + "inbound_real_time_payments_transfer.created", + "inbound_real_time_payments_transfer.updated", + "inbound_wire_drawdown_request.created", + "inbound_wire_transfer.created", + "inbound_wire_transfer.updated", + "intrafi_account_enrollment.created", + "intrafi_account_enrollment.updated", + "intrafi_exclusion.created", + "intrafi_exclusion.updated", + "legacy_card_dispute.created", + "legacy_card_dispute.updated", + "lockbox.created", + "lockbox.updated", + "oauth_connection.created", + "oauth_connection.deactivated", + "card_push_transfer.created", + "card_push_transfer.updated", + "card_validation.created", + "card_validation.updated", + "pending_transaction.created", + "pending_transaction.updated", + "physical_card.created", + "physical_card.updated", + "physical_card_profile.created", + "physical_card_profile.updated", + "physical_check.created", + "physical_check.updated", + "program.created", + "program.updated", + "proof_of_authorization_request.created", + "proof_of_authorization_request.updated", + "real_time_decision.card_authorization_requested", + "real_time_decision.card_balance_inquiry_requested", + "real_time_decision.digital_wallet_token_requested", + "real_time_decision.digital_wallet_authentication_requested", + "real_time_decision.card_authentication_requested", + "real_time_decision.card_authentication_challenge_requested", + "real_time_payments_transfer.created", + "real_time_payments_transfer.updated", + "real_time_payments_request_for_payment.created", + "real_time_payments_request_for_payment.updated", + "swift_transfer.created", + "swift_transfer.updated", + "transaction.created", + "wire_drawdown_request.created", + "wire_drawdown_request.updated", + "wire_transfer.created", + "wire_transfer.updated", + ] + ] + """The category of the Event to subscribe to. - `account.created` - Occurs whenever an Account is created. - `account.updated` - Occurs whenever an Account is updated. @@ -137,6 +169,18 @@ class EventSubscriptionCreateParams(TypedDict, total=False): updated. - `ach_transfer.created` - Occurs whenever an ACH Transfer is created. - `ach_transfer.updated` - Occurs whenever an ACH Transfer is updated. + - `blockchain_address.created` - Occurs whenever a Blockchain Address is + created. + - `blockchain_address.updated` - Occurs whenever a Blockchain Address is + updated. + - `blockchain_offramp_transfer.created` - Occurs whenever a Blockchain Off-Ramp + Transfer is created. + - `blockchain_offramp_transfer.updated` - Occurs whenever a Blockchain Off-Ramp + Transfer is updated. + - `blockchain_onramp_transfer.created` - Occurs whenever a Blockchain On-Ramp + Transfer is created. + - `blockchain_onramp_transfer.updated` - Occurs whenever a Blockchain On-Ramp + Transfer is updated. - `bookkeeping_account.created` - Occurs whenever a Bookkeeping Account is created. - `bookkeeping_account.updated` - Occurs whenever a Bookkeeping Account is @@ -241,6 +285,8 @@ class EventSubscriptionCreateParams(TypedDict, total=False): created. - `physical_card_profile.updated` - Occurs whenever a Physical Card Profile is updated. + - `physical_check.created` - Occurs whenever a Physical Check is created. + - `physical_check.updated` - Occurs whenever a Physical Check is updated. - `program.created` - Occurs whenever a Program is created. - `program.updated` - Occurs whenever a Program is updated. - `proof_of_authorization_request.created` - Occurs whenever a Proof of @@ -279,17 +325,3 @@ class EventSubscriptionCreateParams(TypedDict, total=False): - `wire_transfer.created` - Occurs whenever a Wire Transfer is created. - `wire_transfer.updated` - Occurs whenever a Wire Transfer is updated. """ - - shared_secret: str - """The key that will be used to sign webhooks. - - If no value is passed, a random string will be used as default. - """ - - status: Literal["active", "disabled"] - """The status of the event subscription. Defaults to `active` if not specified. - - - `active` - The subscription is active and Events will be delivered normally. - - `disabled` - The subscription is temporarily disabled and Events will not be - delivered. - """ diff --git a/src/increase/types/export.py b/src/increase/types/export.py index 4ec5c7719..9245bab31 100644 --- a/src/increase/types/export.py +++ b/src/increase/types/export.py @@ -1,12 +1,284 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional -from datetime import datetime +from typing import TYPE_CHECKING, Dict, List, Optional +from datetime import date, datetime from typing_extensions import Literal +from pydantic import Field as FieldInfo + from .._models import BaseModel -__all__ = ["Export"] +__all__ = [ + "Export", + "AccountStatementBai2", + "AccountStatementOfx", + "AccountStatementOfxCreatedAt", + "AccountVerificationLetter", + "BalanceCsv", + "BalanceCsvCreatedAt", + "BookkeepingAccountBalanceCsv", + "BookkeepingAccountBalanceCsvCreatedAt", + "DashboardTableCsv", + "EntityCsv", + "FeeCsv", + "FeeCsvCreatedAt", + "Form1099Int", + "Form1099Misc", + "FundingInstructions", + "Result", + "TransactionCsv", + "TransactionCsvCreatedAt", + "VendorCsv", + "VoidedCheck", + "VoidedCheckPayer", +] + + +class AccountStatementBai2(BaseModel): + """Details of the account statement BAI2 export. + + This field will be present when the `category` is equal to `account_statement_bai2`. + """ + + account_id: Optional[str] = None + """Filter results by Account.""" + + effective_date: Optional[date] = None + """The date for which to retrieve the balance.""" + + program_id: Optional[str] = None + """Filter results by Program.""" + + +class AccountStatementOfxCreatedAt(BaseModel): + """Filter transactions by their created date.""" + + after: Optional[datetime] = None + """Filter results to transactions created after this time.""" + + before: Optional[datetime] = None + """Filter results to transactions created before this time.""" + + +class AccountStatementOfx(BaseModel): + """Details of the account statement OFX export. + + This field will be present when the `category` is equal to `account_statement_ofx`. + """ + + account_id: str + """The Account to create a statement for.""" + + created_at: Optional[AccountStatementOfxCreatedAt] = None + """Filter transactions by their created date.""" + + +class AccountVerificationLetter(BaseModel): + """Details of the account verification letter export. + + This field will be present when the `category` is equal to `account_verification_letter`. + """ + + account_number_id: str + """The Account Number to create a letter for.""" + + balance_date: Optional[date] = None + """The date of the balance to include in the letter.""" + + +class BalanceCsvCreatedAt(BaseModel): + """Filter balances by their created date.""" + + after: Optional[datetime] = None + """Filter balances created after this time.""" + + before: Optional[datetime] = None + """Filter balances created before this time.""" + + +class BalanceCsv(BaseModel): + """Details of the balance CSV export. + + This field will be present when the `category` is equal to `balance_csv`. + """ + + account_id: Optional[str] = None + """Filter results by Account.""" + + created_at: Optional[BalanceCsvCreatedAt] = None + """Filter balances by their created date.""" + + +class BookkeepingAccountBalanceCsvCreatedAt(BaseModel): + """Filter balances by their created date.""" + + after: Optional[datetime] = None + """Filter balances created after this time.""" + + before: Optional[datetime] = None + """Filter balances created before this time.""" + + +class BookkeepingAccountBalanceCsv(BaseModel): + """Details of the bookkeeping account balance CSV export. + + This field will be present when the `category` is equal to `bookkeeping_account_balance_csv`. + """ + + bookkeeping_account_id: Optional[str] = None + """Filter results by Bookkeeping Account.""" + + created_at: Optional[BookkeepingAccountBalanceCsvCreatedAt] = None + """Filter balances by their created date.""" + + +class DashboardTableCsv(BaseModel): + """Details of the dashboard table CSV export. + + This field will be present when the `category` is equal to `dashboard_table_csv`. + """ + + pass + + +class EntityCsv(BaseModel): + """Details of the entity CSV export. + + This field will be present when the `category` is equal to `entity_csv`. + """ + + pass + + +class FeeCsvCreatedAt(BaseModel): + """Filter fees by their created date. + + The time range must not include any fees that are part of an open fee statement. + """ + + after: Optional[datetime] = None + """Filter fees created after this time.""" + + before: Optional[datetime] = None + """Filter fees created before this time.""" + + +class FeeCsv(BaseModel): + """Details of the fee CSV export. + + This field will be present when the `category` is equal to `fee_csv`. + """ + + created_at: Optional[FeeCsvCreatedAt] = None + """Filter fees by their created date. + + The time range must not include any fees that are part of an open fee statement. + """ + + +class Form1099Int(BaseModel): + """Details of the Form 1099-INT export. + + This field will be present when the `category` is equal to `form_1099_int`. + """ + + account_id: str + """The Account the tax form is for.""" + + corrected: bool + """Whether the tax form is a corrected form.""" + + description: str + """A description of the tax form.""" + + year: int + """The tax year for the tax form.""" + + +class Form1099Misc(BaseModel): + """Details of the Form 1099-MISC export. + + This field will be present when the `category` is equal to `form_1099_misc`. + """ + + account_id: str + """The Account the tax form is for.""" + + corrected: bool + """Whether the tax form is a corrected form.""" + + year: int + """The tax year for the tax form.""" + + +class FundingInstructions(BaseModel): + """Details of the funding instructions export. + + This field will be present when the `category` is equal to `funding_instructions`. + """ + + account_number_id: str + """The Account Number to create funding instructions for.""" + + +class Result(BaseModel): + """The result of the Export. + + This will be present when the Export's status transitions to `complete`. + """ + + file_id: str + """The File containing the contents of the Export.""" + + +class TransactionCsvCreatedAt(BaseModel): + """Filter transactions by their created date.""" + + after: Optional[datetime] = None + """Filter transactions created after this time.""" + + before: Optional[datetime] = None + """Filter transactions created before this time.""" + + +class TransactionCsv(BaseModel): + """Details of the transaction CSV export. + + This field will be present when the `category` is equal to `transaction_csv`. + """ + + account_id: Optional[str] = None + """Filter results by Account.""" + + created_at: Optional[TransactionCsvCreatedAt] = None + """Filter transactions by their created date.""" + + +class VendorCsv(BaseModel): + """Details of the vendor CSV export. + + This field will be present when the `category` is equal to `vendor_csv`. + """ + + pass + + +class VoidedCheckPayer(BaseModel): + line: str + """The contents of the line.""" + + +class VoidedCheck(BaseModel): + """Details of the voided check export. + + This field will be present when the `category` is equal to `voided_check`. + """ + + account_number_id: str + """The Account Number for the voided check.""" + + payer: List[VoidedCheckPayer] + """The payer information printed on the check.""" class Export(BaseModel): @@ -18,6 +290,40 @@ class Export(BaseModel): id: str """The Export identifier.""" + account_statement_bai2: Optional[AccountStatementBai2] = None + """Details of the account statement BAI2 export. + + This field will be present when the `category` is equal to + `account_statement_bai2`. + """ + + account_statement_ofx: Optional[AccountStatementOfx] = None + """Details of the account statement OFX export. + + This field will be present when the `category` is equal to + `account_statement_ofx`. + """ + + account_verification_letter: Optional[AccountVerificationLetter] = None + """Details of the account verification letter export. + + This field will be present when the `category` is equal to + `account_verification_letter`. + """ + + balance_csv: Optional[BalanceCsv] = None + """Details of the balance CSV export. + + This field will be present when the `category` is equal to `balance_csv`. + """ + + bookkeeping_account_balance_csv: Optional[BookkeepingAccountBalanceCsv] = None + """Details of the bookkeeping account balance CSV export. + + This field will be present when the `category` is equal to + `bookkeeping_account_balance_csv`. + """ + category: Literal[ "account_statement_ofx", "account_statement_bai2", @@ -31,6 +337,8 @@ class Export(BaseModel): "funding_instructions", "form_1099_int", "form_1099_misc", + "fee_csv", + "voided_check", ] """The category of the Export. @@ -55,21 +363,50 @@ class Export(BaseModel): - `funding_instructions` - A PDF of funding instructions. - `form_1099_int` - A PDF of an Internal Revenue Service Form 1099-INT. - `form_1099_misc` - A PDF of an Internal Revenue Service Form 1099-MISC. + - `fee_csv` - Export a CSV of fees. The time range must not include any fees + that are part of an open fee statement. + - `voided_check` - A PDF of a voided check. """ created_at: datetime """The time the Export was created.""" - file_download_url: Optional[str] = None - """A URL at which the Export's file can be downloaded. + dashboard_table_csv: Optional[DashboardTableCsv] = None + """Details of the dashboard table CSV export. - This will be present when the Export's status transitions to `complete`. + This field will be present when the `category` is equal to + `dashboard_table_csv`. """ - file_id: Optional[str] = None - """The File containing the contents of the Export. + entity_csv: Optional[EntityCsv] = None + """Details of the entity CSV export. - This will be present when the Export's status transitions to `complete`. + This field will be present when the `category` is equal to `entity_csv`. + """ + + fee_csv: Optional[FeeCsv] = None + """Details of the fee CSV export. + + This field will be present when the `category` is equal to `fee_csv`. + """ + + form_1099_int: Optional[Form1099Int] = None + """Details of the Form 1099-INT export. + + This field will be present when the `category` is equal to `form_1099_int`. + """ + + form_1099_misc: Optional[Form1099Misc] = None + """Details of the Form 1099-MISC export. + + This field will be present when the `category` is equal to `form_1099_misc`. + """ + + funding_instructions: Optional[FundingInstructions] = None + """Details of the funding instructions export. + + This field will be present when the `category` is equal to + `funding_instructions`. """ idempotency_key: Optional[str] = None @@ -80,6 +417,12 @@ class Export(BaseModel): [idempotency](https://increase.com/documentation/idempotency-keys). """ + result: Optional[Result] = None + """The result of the Export. + + This will be present when the Export's status transitions to `complete`. + """ + status: Literal["pending", "complete", "failed"] """The status of the Export. @@ -89,8 +432,38 @@ class Export(BaseModel): resolve the issue. """ + transaction_csv: Optional[TransactionCsv] = None + """Details of the transaction CSV export. + + This field will be present when the `category` is equal to `transaction_csv`. + """ + type: Literal["export"] """A constant representing the object's type. For this resource it will always be `export`. """ + + vendor_csv: Optional[VendorCsv] = None + """Details of the vendor CSV export. + + This field will be present when the `category` is equal to `vendor_csv`. + """ + + voided_check: Optional[VoidedCheck] = None + """Details of the voided check export. + + This field will be present when the `category` is equal to `voided_check`. + """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/export_create_params.py b/src/increase/types/export_create_params.py index 47ce43b19..e031a09a4 100644 --- a/src/increase/types/export_create_params.py +++ b/src/increase/types/export_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Union +from typing import Union, Iterable from datetime import date, datetime from typing_extensions import Literal, Required, Annotated, TypedDict @@ -19,11 +19,12 @@ "BookkeepingAccountBalanceCsv", "BookkeepingAccountBalanceCsvCreatedAt", "EntityCsv", - "EntityCsvStatus", "FundingInstructions", "TransactionCsv", "TransactionCsvCreatedAt", "VendorCsv", + "VoidedCheck", + "VoidedCheckPayer", ] @@ -39,6 +40,7 @@ class ExportCreateParams(TypedDict, total=False): "vendor_csv", "account_verification_letter", "funding_instructions", + "voided_check", ] ] """The type of Export to create. @@ -57,6 +59,7 @@ class ExportCreateParams(TypedDict, total=False): management dashboard. - `account_verification_letter` - A PDF of an account verification letter. - `funding_instructions` - A PDF of funding instructions. + - `voided_check` - A PDF of a voided check. """ account_statement_bai2: AccountStatementBai2 @@ -113,6 +116,12 @@ class ExportCreateParams(TypedDict, total=False): Required if `category` is equal to `vendor_csv`. """ + voided_check: VoidedCheck + """Options for the created export. + + Required if `category` is equal to `voided_check`. + """ + class AccountStatementBai2(TypedDict, total=False): """Options for the created export. @@ -230,14 +239,11 @@ class BalanceCsv(TypedDict, total=False): """ account_id: str - """Filter exported Transactions to the specified Account.""" + """Filter exported Balances to the specified Account.""" created_at: BalanceCsvCreatedAt """Filter results by time range on the `created_at` attribute.""" - program_id: str - """Filter exported Transactions to the specified Program.""" - class BookkeepingAccountBalanceCsvCreatedAt(TypedDict, total=False): """Filter results by time range on the `created_at` attribute.""" @@ -274,35 +280,22 @@ class BookkeepingAccountBalanceCsv(TypedDict, total=False): """ bookkeeping_account_id: str - """Filter exported Transactions to the specified Bookkeeping Account.""" + """ + Filter exported Bookkeeping Account Balances to the specified Bookkeeping + Account. + """ created_at: BookkeepingAccountBalanceCsvCreatedAt """Filter results by time range on the `created_at` attribute.""" -_EntityCsvStatusReservedKeywords = TypedDict( - "_EntityCsvStatusReservedKeywords", - { - "in": List[Literal["active", "archived", "disabled"]], - }, - total=False, -) - - -class EntityCsvStatus(_EntityCsvStatusReservedKeywords, total=False): - """Entity statuses to filter by.""" - - pass - - class EntityCsv(TypedDict, total=False): """Options for the created export. Required if `category` is equal to `entity_csv`. """ - status: EntityCsvStatus - """Entity statuses to filter by.""" + pass class FundingInstructions(TypedDict, total=False): @@ -355,9 +348,6 @@ class TransactionCsv(TypedDict, total=False): created_at: TransactionCsvCreatedAt """Filter results by time range on the `created_at` attribute.""" - program_id: str - """Filter exported Transactions to the specified Program.""" - class VendorCsv(TypedDict, total=False): """Options for the created export. @@ -366,3 +356,21 @@ class VendorCsv(TypedDict, total=False): """ pass + + +class VoidedCheckPayer(TypedDict, total=False): + line: Required[str] + """The contents of the line.""" + + +class VoidedCheck(TypedDict, total=False): + """Options for the created export. + + Required if `category` is equal to `voided_check`. + """ + + account_number_id: Required[str] + """The Account Number for the voided check.""" + + payer: Iterable[VoidedCheckPayer] + """The payer information to be printed on the check.""" diff --git a/src/increase/types/export_list_params.py b/src/increase/types/export_list_params.py index 3ba2c1ea6..fa126d6a8 100644 --- a/src/increase/types/export_list_params.py +++ b/src/increase/types/export_list_params.py @@ -8,17 +8,60 @@ from .._utils import PropertyInfo -__all__ = ["ExportListParams", "Category", "CreatedAt", "Status"] +__all__ = ["ExportListParams", "CreatedAt", "Form1099Int", "Form1099Misc", "Status"] class ExportListParams(TypedDict, total=False): - category: Category + category: Literal[ + "account_statement_ofx", + "account_statement_bai2", + "transaction_csv", + "balance_csv", + "bookkeeping_account_balance_csv", + "entity_csv", + "vendor_csv", + "dashboard_table_csv", + "account_verification_letter", + "funding_instructions", + "form_1099_int", + "form_1099_misc", + "fee_csv", + "voided_check", + ] + """Filter Exports for those with the specified category. + + - `account_statement_ofx` - Export an Open Financial Exchange (OFX) file of + transactions and balances for a given time range and Account. + - `account_statement_bai2` - Export a BAI2 file of transactions and balances for + a given date and optional Account. + - `transaction_csv` - Export a CSV of all transactions for a given time range. + - `balance_csv` - Export a CSV of account balances for the dates in a given + range. + - `bookkeeping_account_balance_csv` - Export a CSV of bookkeeping account + balances for the dates in a given range. + - `entity_csv` - Export a CSV of entities with a given status. + - `vendor_csv` - Export a CSV of vendors added to the third-party risk + management dashboard. + - `dashboard_table_csv` - Certain dashboard tables are available as CSV exports. + This export cannot be created via the API. + - `account_verification_letter` - A PDF of an account verification letter. + - `funding_instructions` - A PDF of funding instructions. + - `form_1099_int` - A PDF of an Internal Revenue Service Form 1099-INT. + - `form_1099_misc` - A PDF of an Internal Revenue Service Form 1099-MISC. + - `fee_csv` - Export a CSV of fees. The time range must not include any fees + that are part of an open fee statement. + - `voided_check` - A PDF of a voided check. + """ created_at: CreatedAt cursor: str """Return the page of entries after this one.""" + form_1099_int: Form1099Int + + form_1099_misc: Form1099Misc + idempotency_key: str """ Filter records to the one with the specified `idempotency_key` you chose for @@ -36,34 +79,6 @@ class ExportListParams(TypedDict, total=False): status: Status -_CategoryReservedKeywords = TypedDict( - "_CategoryReservedKeywords", - { - "in": List[ - Literal[ - "account_statement_ofx", - "account_statement_bai2", - "transaction_csv", - "balance_csv", - "bookkeeping_account_balance_csv", - "entity_csv", - "vendor_csv", - "dashboard_table_csv", - "account_verification_letter", - "funding_instructions", - "form_1099_int", - "form_1099_misc", - ] - ], - }, - total=False, -) - - -class Category(_CategoryReservedKeywords, total=False): - pass - - class CreatedAt(TypedDict, total=False): after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] """ @@ -90,6 +105,16 @@ class CreatedAt(TypedDict, total=False): """ +class Form1099Int(TypedDict, total=False): + account_id: str + """Filter Form 1099-INT Exports to those for the specified Account.""" + + +class Form1099Misc(TypedDict, total=False): + account_id: str + """Filter Form 1099-MISC Exports to those for the specified Account.""" + + _StatusReservedKeywords = TypedDict( "_StatusReservedKeywords", { diff --git a/src/increase/types/fednow_transfer.py b/src/increase/types/fednow_transfer.py index 03bf44291..cefd454e1 100644 --- a/src/increase/types/fednow_transfer.py +++ b/src/increase/types/fednow_transfer.py @@ -13,6 +13,7 @@ "CreatedByAPIKey", "CreatedByOAuthApplication", "CreatedByUser", + "CreditorAddress", "Rejection", "Submission", ] @@ -51,9 +52,6 @@ class CreatedByUser(BaseModel): class CreatedBy(BaseModel): """What object created the transfer, either via the API or the dashboard.""" - api_key: Optional[CreatedByAPIKey] = None - """If present, details about the API key that created the transfer.""" - category: Literal["api_key", "oauth_application", "user"] """The type of object that created this transfer. @@ -64,6 +62,9 @@ class CreatedBy(BaseModel): object. """ + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + oauth_application: Optional[CreatedByOAuthApplication] = None """If present, details about the OAuth Application that created the transfer.""" @@ -71,6 +72,22 @@ class CreatedBy(BaseModel): """If present, details about the User that created the transfer.""" +class CreditorAddress(BaseModel): + """The creditor's address.""" + + city: Optional[str] = None + """The city, district, town, or village of the address.""" + + line1: Optional[str] = None + """The first line of the address.""" + + postal_code: Optional[str] = None + """The ZIP code of the address.""" + + state: Optional[str] = None + """The address state.""" + + class Rejection(BaseModel): """ If the transfer is rejected by FedNow or the destination financial institution, this will contain supplemental details. @@ -185,6 +202,9 @@ class FednowTransfer(BaseModel): created_by: Optional[CreatedBy] = None """What object created the transfer, either via the API or the dashboard.""" + creditor_address: Optional[CreditorAddress] = None + """The creditor's address.""" + creditor_name: str """The name of the transfer's recipient. diff --git a/src/increase/types/file.py b/src/increase/types/file.py index 8391769aa..45939cdbb 100644 --- a/src/increase/types/file.py +++ b/src/increase/types/file.py @@ -73,6 +73,7 @@ class File(BaseModel): "document_request", "entity_supplemental_document", "export", + "fee_statement", "unusual_activity_report_attachment", "deposit_account_control_agreement", "proof_of_authorization_request_submission", @@ -124,6 +125,7 @@ class File(BaseModel): - `entity_supplemental_document` - A supplemental document associated an an Entity. - `export` - The results of an Export you requested via the dashboard or API. + - `fee_statement` - A fee statement. - `unusual_activity_report_attachment` - An attachment to an Unusual Activity Report. - `deposit_account_control_agreement` - A document granting another entity diff --git a/src/increase/types/file_link_create_params.py b/src/increase/types/file_link_create_params.py index 8707daaa8..e41647b08 100644 --- a/src/increase/types/file_link_create_params.py +++ b/src/increase/types/file_link_create_params.py @@ -18,6 +18,6 @@ class FileLinkCreateParams(TypedDict, total=False): expires_at: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] """The time at which the File Link will expire. - The default is 1 hour from the time of the request. The maxiumum is 1 day from + The default is 1 hour from the time of the request. The maximum is 1 day from the time of the request. """ diff --git a/src/increase/types/file_list_params.py b/src/increase/types/file_list_params.py index b87680357..2e6f4332b 100644 --- a/src/increase/types/file_list_params.py +++ b/src/increase/types/file_list_params.py @@ -90,6 +90,7 @@ class CreatedAt(TypedDict, total=False): "document_request", "entity_supplemental_document", "export", + "fee_statement", "unusual_activity_report_attachment", "deposit_account_control_agreement", "proof_of_authorization_request_submission", diff --git a/src/increase/types/inbound_ach_transfer.py b/src/increase/types/inbound_ach_transfer.py index bce55afef..266877d86 100644 --- a/src/increase/types/inbound_ach_transfer.py +++ b/src/increase/types/inbound_ach_transfer.py @@ -1,9 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import TYPE_CHECKING, Dict, List, Optional from datetime import date, datetime from typing_extensions import Literal +from pydantic import Field as FieldInfo + from .._models import BaseModel __all__ = [ @@ -355,7 +357,7 @@ class NotificationOfChange(BaseModel): """The new account number provided in the notification of change.""" updated_routing_number: Optional[str] = None - """The new account number provided in the notification of change.""" + """The new routing number provided in the notification of change.""" class Settlement(BaseModel): @@ -583,3 +585,15 @@ class InboundACHTransfer(BaseModel): For this resource it will always be `inbound_ach_transfer`. """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/inbound_check_deposit.py b/src/increase/types/inbound_check_deposit.py index 0e715e1a3..d77515925 100644 --- a/src/increase/types/inbound_check_deposit.py +++ b/src/increase/types/inbound_check_deposit.py @@ -46,6 +46,7 @@ class DepositReturn(BaseModel): "duplicate_presentment", "endorsement_missing", "endorsement_irregular", + "refer_to_maker", ] """The reason the deposit was returned. @@ -54,6 +55,7 @@ class DepositReturn(BaseModel): - `duplicate_presentment` - The check was a duplicate presentment. - `endorsement_missing` - The check was not endorsed. - `endorsement_irregular` - The check was not endorsed by the payee. + - `refer_to_maker` - The maker of the check requested its return. """ returned_at: datetime diff --git a/src/increase/types/inbound_check_deposit_return_params.py b/src/increase/types/inbound_check_deposit_return_params.py index 0ca8f79f8..b47aaf81b 100644 --- a/src/increase/types/inbound_check_deposit_return_params.py +++ b/src/increase/types/inbound_check_deposit_return_params.py @@ -15,6 +15,7 @@ class InboundCheckDepositReturnParams(TypedDict, total=False): "duplicate_presentment", "endorsement_missing", "endorsement_irregular", + "refer_to_maker", ] ] """The reason to return the Inbound Check Deposit. @@ -24,4 +25,5 @@ class InboundCheckDepositReturnParams(TypedDict, total=False): - `duplicate_presentment` - The check was a duplicate presentment. - `endorsement_missing` - The check was not endorsed. - `endorsement_irregular` - The check was not endorsed by the payee. + - `refer_to_maker` - The maker of the check requested its return. """ diff --git a/src/increase/types/inbound_wire_drawdown_request.py b/src/increase/types/inbound_wire_drawdown_request.py index 25b06446b..b6ffce482 100644 --- a/src/increase/types/inbound_wire_drawdown_request.py +++ b/src/increase/types/inbound_wire_drawdown_request.py @@ -25,7 +25,7 @@ class InboundWireDrawdownRequest(BaseModel): created_at: datetime """ The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which - the inbound wire drawdown requested was created. + the inbound wire drawdown request was created. """ creditor_account_number: str diff --git a/src/increase/types/inbound_wire_transfer.py b/src/increase/types/inbound_wire_transfer.py index 5c4993263..c7cb18c0f 100644 --- a/src/increase/types/inbound_wire_transfer.py +++ b/src/increase/types/inbound_wire_transfer.py @@ -8,14 +8,25 @@ from .._models import BaseModel -__all__ = ["InboundWireTransfer", "Reversal"] +__all__ = ["InboundWireTransfer", "Acceptance", "Reversal"] -class Reversal(BaseModel): +class Acceptance(BaseModel): + """If the transfer is accepted, this will contain details of the acceptance.""" + + accepted_at: datetime """ - Information about the reversal of the inbound wire transfer if it has been reversed. + The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which + the transfer was accepted. """ + transaction_id: str + """The identifier of the transaction for the accepted transfer.""" + + +class Reversal(BaseModel): + """If the transfer is reversed, this will contain details of the reversal.""" + reason: Literal["duplicate", "creditor_request", "transaction_forbidden"] """The reason for the reversal. @@ -40,6 +51,9 @@ class InboundWireTransfer(BaseModel): id: str """The inbound wire transfer's identifier.""" + acceptance: Optional[Acceptance] = None + """If the transfer is accepted, this will contain details of the acceptance.""" + account_id: str """The Account to which the transfer belongs.""" @@ -102,10 +116,7 @@ class InboundWireTransfer(BaseModel): """The sending bank's identifier for the wire transfer.""" reversal: Optional[Reversal] = None - """ - Information about the reversal of the inbound wire transfer if it has been - reversed. - """ + """If the transfer is reversed, this will contain details of the reversal.""" status: Literal["pending", "accepted", "declined", "reversed"] """The status of the transfer. diff --git a/src/increase/types/intrafi_exclusion.py b/src/increase/types/intrafi_exclusion.py index 6e99025ba..bca24828e 100644 --- a/src/increase/types/intrafi_exclusion.py +++ b/src/increase/types/intrafi_exclusion.py @@ -17,7 +17,7 @@ class IntrafiExclusion(BaseModel): id: str """The identifier of this exclusion request.""" - bank_name: str + bank_name: Optional[str] = None """The name of the excluded institution.""" created_at: datetime @@ -46,12 +46,14 @@ class IntrafiExclusion(BaseModel): [idempotency](https://increase.com/documentation/idempotency-keys). """ - status: Literal["pending", "completed", "archived"] + status: Literal["pending", "completed", "archived", "ineligible"] """The status of the exclusion request. - `pending` - The exclusion is being added to the IntraFi network. - `completed` - The exclusion has been added to the IntraFi network. - `archived` - The exclusion has been removed from the IntraFi network. + - `ineligible` - The exclusion wasn't eligible to be added to the IntraFi + network. """ submitted_at: Optional[datetime] = None diff --git a/src/increase/types/intrafi_exclusion_create_params.py b/src/increase/types/intrafi_exclusion_create_params.py index 1a0c78dc3..62926b177 100644 --- a/src/increase/types/intrafi_exclusion_create_params.py +++ b/src/increase/types/intrafi_exclusion_create_params.py @@ -8,8 +8,14 @@ class IntrafiExclusionCreateParams(TypedDict, total=False): - bank_name: Required[str] - """The name of the financial institution to be excluded.""" - entity_id: Required[str] """The identifier of the Entity whose deposits will be excluded.""" + + fdic_certificate_number: Required[str] + """The FDIC certificate number of the financial institution to be excluded. + + An FDIC certificate number uniquely identifies a financial institution, and is + different than a routing number. To find one, we recommend searching by Bank + Name using the + [FDIC's bankfind tool](https://banks.data.fdic.gov/bankfind-suite/bankfind). + """ diff --git a/src/increase/types/lockbox.py b/src/increase/types/lockbox.py index 283784228..76a76c374 100644 --- a/src/increase/types/lockbox.py +++ b/src/increase/types/lockbox.py @@ -1,9 +1,11 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import TYPE_CHECKING, Dict, Optional from datetime import datetime from typing_extensions import Literal +from pydantic import Field as FieldInfo + from .._models import BaseModel __all__ = ["Lockbox", "Address"] @@ -91,3 +93,15 @@ class Lockbox(BaseModel): For this resource it will always be `lockbox`. """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/pending_transaction.py b/src/increase/types/pending_transaction.py index aba8ee0eb..9eba210fc 100644 --- a/src/increase/types/pending_transaction.py +++ b/src/increase/types/pending_transaction.py @@ -13,6 +13,8 @@ "Source", "SourceAccountTransferInstruction", "SourceACHTransferInstruction", + "SourceBlockchainOfframpTransferInstruction", + "SourceBlockchainOnrampTransferInstruction", "SourceCardAuthorization", "SourceCardAuthorizationAdditionalAmounts", "SourceCardAuthorizationAdditionalAmountsClinic", @@ -32,6 +34,7 @@ "SourceCardAuthorizationVerification", "SourceCardAuthorizationVerificationCardVerificationCode", "SourceCardAuthorizationVerificationCardholderAddress", + "SourceCardAuthorizationVerificationCardholderName", "SourceCardPushTransferInstruction", "SourceCheckDepositInstruction", "SourceCheckTransferInstruction", @@ -106,6 +109,52 @@ def __getattr__(self, attr: str) -> object: ... __pydantic_extra__: Dict[str, object] +class SourceBlockchainOfframpTransferInstruction(BaseModel): + """A Blockchain Off-Ramp Transfer Instruction object. + + This field will be present in the JSON response if and only if `category` is equal to `blockchain_offramp_transfer_instruction`. + """ + + source_blockchain_address_id: str + """The identifier of the Blockchain Address the funds were received at.""" + + transfer_id: str + """ + The identifier of the Blockchain Off-Ramp Transfer that led to this Transaction. + """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] + + +class SourceBlockchainOnrampTransferInstruction(BaseModel): + """A Blockchain On-Ramp Transfer Instruction object. + + This field will be present in the JSON response if and only if `category` is equal to `blockchain_onramp_transfer_instruction`. + """ + + amount: int + """The transfer amount in USD cents.""" + + destination_blockchain_address: str + """The blockchain address the funds are being sent to.""" + + transfer_id: str + """ + The identifier of the Blockchain On-Ramp Transfer that led to this Pending + Transaction. + """ + + class SourceCardAuthorizationAdditionalAmountsClinic(BaseModel): """The part of this transaction amount that was for clinic-related services.""" @@ -410,6 +459,7 @@ class SourceCardAuthorizationNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -424,8 +474,10 @@ class SourceCardAuthorizationNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -441,6 +493,41 @@ class SourceCardAuthorizationNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class SourceCardAuthorizationNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -546,6 +633,19 @@ class SourceCardAuthorizationVerificationCardholderAddress(BaseModel): """ +class SourceCardAuthorizationVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class SourceCardAuthorizationVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -561,11 +661,14 @@ class SourceCardAuthorizationVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[SourceCardAuthorizationVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class SourceCardAuthorization(BaseModel): """A Card Authorization object. - This field will be present in the JSON response if and only if `category` is equal to `card_authorization`. Card Authorizations are temporary holds placed on a customers funds with the intent to later clear a transaction. + This field will be present in the JSON response if and only if `category` is equal to `card_authorization`. Card Authorizations are temporary holds placed on a customer's funds with the intent to later clear a transaction. """ id: str @@ -1053,35 +1156,6 @@ class Source(BaseModel): This is an object giving more details on the network-level event that caused the Pending Transaction. For example, for a card transaction this lists the merchant's industry and location. """ - account_transfer_instruction: Optional[SourceAccountTransferInstruction] = None - """An Account Transfer Instruction object. - - This field will be present in the JSON response if and only if `category` is - equal to `account_transfer_instruction`. - """ - - ach_transfer_instruction: Optional[SourceACHTransferInstruction] = None - """An ACH Transfer Instruction object. - - This field will be present in the JSON response if and only if `category` is - equal to `ach_transfer_instruction`. - """ - - card_authorization: Optional[SourceCardAuthorization] = None - """A Card Authorization object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_authorization`. Card Authorizations are temporary holds placed on - a customers funds with the intent to later clear a transaction. - """ - - card_push_transfer_instruction: Optional[SourceCardPushTransferInstruction] = None - """A Card Push Transfer Instruction object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_push_transfer_instruction`. - """ - category: Literal[ "account_transfer_instruction", "ach_transfer_instruction", @@ -1096,6 +1170,8 @@ class Source(BaseModel): "inbound_wire_transfer_reversal", "swift_transfer_instruction", "card_push_transfer_instruction", + "blockchain_onramp_transfer_instruction", + "blockchain_offramp_transfer_instruction", "other", ] """The type of the resource. @@ -1130,10 +1206,59 @@ class Source(BaseModel): under the `swift_transfer_instruction` object. - `card_push_transfer_instruction` - Card Push Transfer Instruction: details will be under the `card_push_transfer_instruction` object. + - `blockchain_onramp_transfer_instruction` - Blockchain On-Ramp Transfer + Instruction: details will be under the + `blockchain_onramp_transfer_instruction` object. + - `blockchain_offramp_transfer_instruction` - Blockchain Off-Ramp Transfer + Instruction: details will be under the + `blockchain_offramp_transfer_instruction` object. - `other` - The Pending Transaction was made for an undocumented or deprecated reason. """ + account_transfer_instruction: Optional[SourceAccountTransferInstruction] = None + """An Account Transfer Instruction object. + + This field will be present in the JSON response if and only if `category` is + equal to `account_transfer_instruction`. + """ + + ach_transfer_instruction: Optional[SourceACHTransferInstruction] = None + """An ACH Transfer Instruction object. + + This field will be present in the JSON response if and only if `category` is + equal to `ach_transfer_instruction`. + """ + + blockchain_offramp_transfer_instruction: Optional[SourceBlockchainOfframpTransferInstruction] = None + """A Blockchain Off-Ramp Transfer Instruction object. + + This field will be present in the JSON response if and only if `category` is + equal to `blockchain_offramp_transfer_instruction`. + """ + + blockchain_onramp_transfer_instruction: Optional[SourceBlockchainOnrampTransferInstruction] = None + """A Blockchain On-Ramp Transfer Instruction object. + + This field will be present in the JSON response if and only if `category` is + equal to `blockchain_onramp_transfer_instruction`. + """ + + card_authorization: Optional[SourceCardAuthorization] = None + """A Card Authorization object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_authorization`. Card Authorizations are temporary holds placed on + a customer's funds with the intent to later clear a transaction. + """ + + card_push_transfer_instruction: Optional[SourceCardPushTransferInstruction] = None + """A Card Push Transfer Instruction object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_push_transfer_instruction`. + """ + check_deposit_instruction: Optional[SourceCheckDepositInstruction] = None """A Check Deposit Instruction object. diff --git a/src/increase/types/pending_transaction_list_params.py b/src/increase/types/pending_transaction_list_params.py index 49494bc33..64ffeb23c 100644 --- a/src/increase/types/pending_transaction_list_params.py +++ b/src/increase/types/pending_transaction_list_params.py @@ -52,6 +52,8 @@ class PendingTransactionListParams(TypedDict, total=False): "inbound_wire_transfer_reversal", "swift_transfer_instruction", "card_push_transfer_instruction", + "blockchain_onramp_transfer_instruction", + "blockchain_offramp_transfer_instruction", "other", ] ], diff --git a/src/increase/types/physical_card_profile.py b/src/increase/types/physical_card_profile.py index e6e35e926..e5c00eba1 100644 --- a/src/increase/types/physical_card_profile.py +++ b/src/increase/types/physical_card_profile.py @@ -38,7 +38,7 @@ class PhysicalCardProfile(BaseModel): created_at: datetime """ The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which - the Card Dispute was created. + the Physical Card Profile was created. """ creator: Literal["increase", "user"] diff --git a/src/increase/types/program.py b/src/increase/types/program.py index bc0b15eea..a85380686 100644 --- a/src/increase/types/program.py +++ b/src/increase/types/program.py @@ -1,14 +1,19 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import TYPE_CHECKING, Dict, Optional +from typing import Optional from datetime import datetime from typing_extensions import Literal -from pydantic import Field as FieldInfo - from .._models import BaseModel -__all__ = ["Program"] +__all__ = ["Program", "Lending"] + + +class Lending(BaseModel): + """The lending details for the program.""" + + maximum_extendable_credit: int + """The maximum extendable credit of the program.""" class Program(BaseModel): @@ -47,6 +52,9 @@ class Program(BaseModel): represented as "0.01". """ + lending: Optional[Lending] = None + """The lending details for the program.""" + name: str """The name of the Program.""" @@ -61,15 +69,3 @@ class Program(BaseModel): The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) time at which the Program was last updated. """ - - if TYPE_CHECKING: - # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a - # value to this field, so for compatibility we avoid doing it at runtime. - __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - - # Stub to indicate that arbitrary properties are accepted. - # To access properties that are not valid identifiers you can use `getattr`, e.g. - # `getattr(obj, '$type')` - def __getattr__(self, attr: str) -> object: ... - else: - __pydantic_extra__: Dict[str, object] diff --git a/src/increase/types/real_time_decision.py b/src/increase/types/real_time_decision.py index 5d891ca4d..64c11f9b0 100644 --- a/src/increase/types/real_time_decision.py +++ b/src/increase/types/real_time_decision.py @@ -11,6 +11,9 @@ __all__ = [ "RealTimeDecision", "CardAuthentication", + "CardAuthenticationDeviceChannel", + "CardAuthenticationDeviceChannelBrowser", + "CardAuthenticationDeviceChannelMerchantInitiated", "CardAuthenticationChallenge", "CardAuthorization", "CardAuthorizationAdditionalAmounts", @@ -36,6 +39,7 @@ "CardAuthorizationVerification", "CardAuthorizationVerificationCardVerificationCode", "CardAuthorizationVerificationCardholderAddress", + "CardAuthorizationVerificationCardholderName", "CardBalanceInquiry", "CardBalanceInquiryAdditionalAmounts", "CardBalanceInquiryAdditionalAmountsClinic", @@ -56,20 +60,173 @@ "CardBalanceInquiryVerification", "CardBalanceInquiryVerificationCardVerificationCode", "CardBalanceInquiryVerificationCardholderAddress", + "CardBalanceInquiryVerificationCardholderName", "DigitalWalletAuthentication", "DigitalWalletToken", "DigitalWalletTokenDevice", ] +class CardAuthenticationDeviceChannelBrowser(BaseModel): + """Fields specific to the browser device channel.""" + + accept_header: Optional[str] = None + """The accept header from the cardholder's browser.""" + + ip_address: Optional[str] = None + """The IP address of the cardholder's browser.""" + + javascript_enabled: Optional[Literal["enabled", "disabled"]] = None + """Whether JavaScript is enabled in the cardholder's browser. + + - `enabled` - JavaScript is enabled in the cardholder's browser. + - `disabled` - JavaScript is not enabled in the cardholder's browser. + """ + + language: Optional[str] = None + """The language of the cardholder's browser.""" + + user_agent: Optional[str] = None + """The user agent of the cardholder's browser.""" + + +class CardAuthenticationDeviceChannelMerchantInitiated(BaseModel): + """Fields specific to merchant initiated transactions.""" + + indicator: Literal[ + "recurring_transaction", + "installment_transaction", + "add_card", + "maintain_card_information", + "account_verification", + "split_delayed_shipment", + "top_up", + "mail_order", + "telephone_order", + "whitelist_status_check", + "other_payment", + "billing_agreement", + "device_binding_status_check", + "card_security_code_status_check", + "delayed_shipment", + "split_payment", + "fido_credential_deletion", + "fido_credential_registration", + "decoupled_authentication_fallback", + ] + """The merchant initiated indicator for the transaction. + + - `recurring_transaction` - Recurring transaction. + - `installment_transaction` - Installment transaction. + - `add_card` - Add card. + - `maintain_card_information` - Maintain card information. + - `account_verification` - Account verification. + - `split_delayed_shipment` - Split or delayed shipment. + - `top_up` - Top up. + - `mail_order` - Mail order. + - `telephone_order` - Telephone order. + - `whitelist_status_check` - Whitelist status check. + - `other_payment` - Other payment. + - `billing_agreement` - Billing agreement. + - `device_binding_status_check` - Device binding status check. + - `card_security_code_status_check` - Card security code status check. + - `delayed_shipment` - Delayed shipment. + - `split_payment` - Split payment. + - `fido_credential_deletion` - FIDO credential deletion. + - `fido_credential_registration` - FIDO credential registration. + - `decoupled_authentication_fallback` - Decoupled authentication fallback. + """ + + +class CardAuthenticationDeviceChannel(BaseModel): + """The device channel of the card authentication attempt.""" + + browser: Optional[CardAuthenticationDeviceChannelBrowser] = None + """Fields specific to the browser device channel.""" + + category: Literal["app", "browser", "three_ds_requestor_initiated"] + """The category of the device channel. + + - `app` - The authentication attempt was made from an app. + - `browser` - The authentication attempt was made from a browser. + - `three_ds_requestor_initiated` - The authentication attempt was initiated by + the 3DS Requestor. + """ + + merchant_initiated: Optional[CardAuthenticationDeviceChannelMerchantInitiated] = None + """Fields specific to merchant initiated transactions.""" + + class CardAuthentication(BaseModel): """Fields related to a 3DS authentication attempt.""" + access_control_server_transaction_id: str + """ + A unique identifier assigned by the Access Control Server (us) for this + transaction. + """ + account_id: str """The identifier of the Account the card belongs to.""" + billing_address_city: Optional[str] = None + """ + The city of the cardholder billing address associated with the card used for + this purchase. + """ + + billing_address_country: Optional[str] = None + """ + The country of the cardholder billing address associated with the card used for + this purchase. + """ + + billing_address_line1: Optional[str] = None + """ + The first line of the cardholder billing address associated with the card used + for this purchase. + """ + + billing_address_line2: Optional[str] = None + """ + The second line of the cardholder billing address associated with the card used + for this purchase. + """ + + billing_address_line3: Optional[str] = None + """ + The third line of the cardholder billing address associated with the card used + for this purchase. + """ + + billing_address_postal_code: Optional[str] = None + """ + The postal code of the cardholder billing address associated with the card used + for this purchase. + """ + + billing_address_state: Optional[str] = None + """ + The US state of the cardholder billing address associated with the card used for + this purchase. + """ + card_id: str - """The identifier of the Card that is being tokenized.""" + """The identifier of the Card.""" + + cardholder_email: Optional[str] = None + """The email address of the cardholder.""" + + cardholder_name: Optional[str] = None + """The name of the cardholder.""" + + category: Optional[Literal["payment_authentication", "non_payment_authentication"]] = None + """The category of the card authentication attempt. + + - `payment_authentication` - The authentication attempt is for a payment. + - `non_payment_authentication` - The authentication attempt is not for a + payment. + """ decision: Optional[Literal["approve", "challenge", "deny"]] = None """Whether or not the authentication attempt was approved. @@ -80,6 +237,163 @@ class CardAuthentication(BaseModel): - `deny` - Deny the authentication attempt. """ + device_channel: CardAuthenticationDeviceChannel + """The device channel of the card authentication attempt.""" + + directory_server_transaction_id: str + """ + A unique identifier assigned by the Directory Server (the card network) for this + transaction. + """ + + merchant_acceptor_id: str + """ + The merchant identifier (commonly abbreviated as MID) of the merchant the card + is transacting with. + """ + + merchant_category_code: str + """ + The Merchant Category Code (commonly abbreviated as MCC) of the merchant the + card is transacting with. + """ + + merchant_country: str + """The country the merchant resides in.""" + + merchant_name: str + """The name of the merchant.""" + + prior_card_authentication_id: Optional[str] = None + """ + The ID of a prior Card Authentication that the requestor used to authenticate + this cardholder for a previous transaction. + """ + + purchase_amount: Optional[int] = None + """The purchase amount in minor units.""" + + purchase_amount_cardholder_estimated: Optional[int] = None + """ + The purchase amount in the cardholder's currency (i.e., USD) estimated using + daily conversion rates from the card network. + """ + + purchase_currency: Optional[str] = None + """ + The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) code for the + authentication attempt's purchase currency. + """ + + requestor_authentication_indicator: Optional[ + Literal[ + "payment_transaction", + "recurring_transaction", + "installment_transaction", + "add_card", + "maintain_card", + "emv_token_cardholder_verification", + "billing_agreement", + ] + ] = None + """ + The 3DS requestor authentication indicator describes why the authentication + attempt is performed, such as for a recurring transaction. + + - `payment_transaction` - The authentication is for a payment transaction. + - `recurring_transaction` - The authentication is for a recurring transaction. + - `installment_transaction` - The authentication is for an installment + transaction. + - `add_card` - The authentication is for adding a card. + - `maintain_card` - The authentication is for maintaining a card. + - `emv_token_cardholder_verification` - The authentication is for EMV token + cardholder verification. + - `billing_agreement` - The authentication is for a billing agreement. + """ + + requestor_challenge_indicator: Optional[ + Literal[ + "no_preference", + "no_challenge_requested", + "challenge_requested_3ds_requestor_preference", + "challenge_requested_mandate", + "no_challenge_requested_transactional_risk_analysis_already_performed", + "no_challenge_requested_data_share_only", + "no_challenge_requested_strong_consumer_authentication_already_performed", + "no_challenge_requested_utilize_whitelist_exemption_if_no_challenge_required", + "challenge_requested_whitelist_prompt_requested_if_challenge_required", + ] + ] = None + """Indicates whether a challenge is requested for this transaction. + + - `no_preference` - No preference. + - `no_challenge_requested` - No challenge requested. + - `challenge_requested_3ds_requestor_preference` - Challenge requested, 3DS + Requestor preference. + - `challenge_requested_mandate` - Challenge requested, mandate. + - `no_challenge_requested_transactional_risk_analysis_already_performed` - No + challenge requested, transactional risk analysis already performed. + - `no_challenge_requested_data_share_only` - No challenge requested, data share + only. + - `no_challenge_requested_strong_consumer_authentication_already_performed` - No + challenge requested, strong consumer authentication already performed. + - `no_challenge_requested_utilize_whitelist_exemption_if_no_challenge_required` - + No challenge requested, utilize whitelist exemption if no challenge required. + - `challenge_requested_whitelist_prompt_requested_if_challenge_required` - + Challenge requested, whitelist prompt requested if challenge required. + """ + + requestor_name: str + """The name of the 3DS requestor.""" + + requestor_url: str + """The URL of the 3DS requestor.""" + + shipping_address_city: Optional[str] = None + """The city of the shipping address associated with this purchase.""" + + shipping_address_country: Optional[str] = None + """The country of the shipping address associated with this purchase.""" + + shipping_address_line1: Optional[str] = None + """The first line of the shipping address associated with this purchase.""" + + shipping_address_line2: Optional[str] = None + """The second line of the shipping address associated with this purchase.""" + + shipping_address_line3: Optional[str] = None + """The third line of the shipping address associated with this purchase.""" + + shipping_address_postal_code: Optional[str] = None + """The postal code of the shipping address associated with this purchase.""" + + shipping_address_state: Optional[str] = None + """The US state of the shipping address associated with this purchase.""" + + three_d_secure_server_transaction_id: str + """ + A unique identifier assigned by the 3DS Server initiating the authentication + attempt for this transaction. + """ + + transaction_type: Optional[ + Literal[ + "goods_service_purchase", + "check_acceptance", + "account_funding", + "quasi_cash_transaction", + "prepaid_activation_and_load", + ] + ] = None + """The type of transaction being authenticated. + + - `goods_service_purchase` - Purchase of goods or services. + - `check_acceptance` - Check acceptance. + - `account_funding` - Account funding. + - `quasi_cash_transaction` - Quasi-cash transaction. + - `prepaid_activation_and_load` - Prepaid activation and load. + """ + upcoming_card_payment_id: str """The identifier of the Card Payment this authentication attempt will belong to. @@ -463,6 +777,7 @@ class CardAuthorizationNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -477,8 +792,10 @@ class CardAuthorizationNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -494,6 +811,41 @@ class CardAuthorizationNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class CardAuthorizationNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -638,6 +990,19 @@ class CardAuthorizationVerificationCardholderAddress(BaseModel): """ +class CardAuthorizationVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class CardAuthorizationVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -653,6 +1018,9 @@ class CardAuthorizationVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[CardAuthorizationVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class CardAuthorization(BaseModel): """Fields related to a card authorization.""" @@ -1174,6 +1542,7 @@ class CardBalanceInquiryNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -1188,8 +1557,10 @@ class CardBalanceInquiryNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -1205,6 +1576,41 @@ class CardBalanceInquiryNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class CardBalanceInquiryNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -1310,6 +1716,19 @@ class CardBalanceInquiryVerificationCardholderAddress(BaseModel): """ +class CardBalanceInquiryVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class CardBalanceInquiryVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -1325,6 +1744,9 @@ class CardBalanceInquiryVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[CardBalanceInquiryVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class CardBalanceInquiry(BaseModel): """Fields related to a card balance inquiry.""" diff --git a/src/increase/types/real_time_decision_action_params.py b/src/increase/types/real_time_decision_action_params.py index decc8849f..5e9eeb31d 100644 --- a/src/increase/types/real_time_decision_action_params.py +++ b/src/increase/types/real_time_decision_action_params.py @@ -2,13 +2,13 @@ from __future__ import annotations -from typing import Dict, Union -from typing_extensions import Literal, Required, TypeAlias, TypedDict +from typing_extensions import Literal, Required, TypedDict __all__ = [ "RealTimeDecisionActionParams", "CardAuthentication", "CardAuthenticationChallenge", + "CardAuthenticationChallengeSuccess", "CardAuthorization", "CardAuthorizationApproval", "CardAuthorizationApprovalCardholderAddressVerificationResult", @@ -76,6 +76,21 @@ class CardAuthentication(TypedDict, total=False): """ +class CardAuthenticationChallengeSuccess(TypedDict, total=False): + """ + If your application was able to deliver the one-time code, this contains metadata about the delivery. + """ + + email: str + """The email address that was used to deliver the one-time code to the cardholder.""" + + phone: str + """ + The phone number that was used to deliver the one-time code to the cardholder + via SMS. + """ + + class CardAuthenticationChallenge(TypedDict, total=False): """ If the Real-Time Decision relates to 3DS card authentication challenge delivery, this object contains your response. @@ -92,6 +107,12 @@ class CardAuthenticationChallenge(TypedDict, total=False): cardholder. """ + success: CardAuthenticationChallengeSuccess + """ + If your application was able to deliver the one-time code, this contains + metadata about the delivery. + """ + class CardAuthorizationApprovalCardholderAddressVerificationResult(TypedDict, total=False): """Your decisions on whether or not each provided address component is a match. @@ -176,7 +197,7 @@ class CardAuthorizationDecline(TypedDict, total=False): """ -class CardAuthorizationTyped(TypedDict, total=False): +class CardAuthorization(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] """ If the Real-Time Decision relates to a card authorization attempt, this object contains your response to the authorization. """ @@ -203,9 +224,6 @@ class CardAuthorizationTyped(TypedDict, total=False): """ -CardAuthorization: TypeAlias = Union[CardAuthorizationTyped, Dict[str, object]] - - class CardBalanceInquiryApproval(TypedDict, total=False): """ If your application approves the balance inquiry, this contains metadata about your decision to approve. diff --git a/src/increase/types/real_time_payments_transfer.py b/src/increase/types/real_time_payments_transfer.py index 127baf9d6..8b7f02d34 100644 --- a/src/increase/types/real_time_payments_transfer.py +++ b/src/increase/types/real_time_payments_transfer.py @@ -91,9 +91,6 @@ class CreatedByUser(BaseModel): class CreatedBy(BaseModel): """What object created the transfer, either via the API or the dashboard.""" - api_key: Optional[CreatedByAPIKey] = None - """If present, details about the API key that created the transfer.""" - category: Literal["api_key", "oauth_application", "user"] """The type of object that created this transfer. @@ -104,6 +101,9 @@ class CreatedBy(BaseModel): object. """ + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + oauth_application: Optional[CreatedByOAuthApplication] = None """If present, details about the OAuth Application that created the transfer.""" diff --git a/src/increase/types/simulations/__init__.py b/src/increase/types/simulations/__init__.py index 36672da70..17ec3a35e 100644 --- a/src/increase/types/simulations/__init__.py +++ b/src/increase/types/simulations/__init__.py @@ -10,13 +10,16 @@ from .ach_transfer_settle_params import ACHTransferSettleParams as ACHTransferSettleParams from .card_dispute_action_params import CardDisputeActionParams as CardDisputeActionParams from .card_reversal_create_params import CardReversalCreateParams as CardReversalCreateParams +from .check_deposit_submit_params import CheckDepositSubmitParams as CheckDepositSubmitParams from .physical_card_create_params import PhysicalCardCreateParams as PhysicalCardCreateParams from .card_increment_create_params import CardIncrementCreateParams as CardIncrementCreateParams from .card_settlement_create_params import CardSettlementCreateParams as CardSettlementCreateParams from .interest_payment_create_params import InterestPaymentCreateParams as InterestPaymentCreateParams from .account_statement_create_params import AccountStatementCreateParams as AccountStatementCreateParams +from .check_deposit_adjustment_params import CheckDepositAdjustmentParams as CheckDepositAdjustmentParams from .inbound_mail_item_create_params import InboundMailItemCreateParams as InboundMailItemCreateParams from .card_authorization_create_params import CardAuthorizationCreateParams as CardAuthorizationCreateParams +from .card_authentication_create_params import CardAuthenticationCreateParams as CardAuthenticationCreateParams from .card_authorization_create_response import CardAuthorizationCreateResponse as CardAuthorizationCreateResponse from .card_balance_inquiry_create_params import CardBalanceInquiryCreateParams as CardBalanceInquiryCreateParams from .inbound_ach_transfer_create_params import InboundACHTransferCreateParams as InboundACHTransferCreateParams @@ -29,6 +32,9 @@ from .physical_card_advance_shipment_params import ( PhysicalCardAdvanceShipmentParams as PhysicalCardAdvanceShipmentParams, ) +from .inbound_check_deposit_adjustment_params import ( + InboundCheckDepositAdjustmentParams as InboundCheckDepositAdjustmentParams, +) from .digital_wallet_token_request_create_params import ( DigitalWalletTokenRequestCreateParams as DigitalWalletTokenRequestCreateParams, ) @@ -44,6 +50,9 @@ from .digital_wallet_token_request_create_response import ( DigitalWalletTokenRequestCreateResponse as DigitalWalletTokenRequestCreateResponse, ) +from .card_authentication_challenge_attempts_params import ( + CardAuthenticationChallengeAttemptsParams as CardAuthenticationChallengeAttemptsParams, +) from .ach_transfer_create_notification_of_change_params import ( ACHTransferCreateNotificationOfChangeParams as ACHTransferCreateNotificationOfChangeParams, ) diff --git a/src/increase/types/simulations/ach_transfer_return_params.py b/src/increase/types/simulations/ach_transfer_return_params.py index 164364c6e..fc6bb2cef 100644 --- a/src/increase/types/simulations/ach_transfer_return_params.py +++ b/src/increase/types/simulations/ach_transfer_return_params.py @@ -85,24 +85,28 @@ class ACHTransferReturnParams(TypedDict, total=False): Defaults to `no_account`. - `insufficient_fund` - Code R01. Insufficient funds in the receiving account. - Sometimes abbreviated to NSF. + Sometimes abbreviated to "NSF." - `no_account` - Code R03. The account does not exist or the receiving bank was unable to locate it. - `account_closed` - Code R02. The account is closed at the receiving bank. - `invalid_account_number_structure` - Code R04. The account number is invalid at the receiving bank. - - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. The account - at the receiving bank was frozen per the Office of Foreign Assets Control. - - `credit_entry_refused_by_receiver` - Code R23. The receiving bank account - refused a credit transfer. + - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. This return + code has two separate meanings. (1) The receiving bank froze the account or + (2) the Office of Foreign Assets Control (OFAC) instructed the receiving bank + to return the entry. + - `credit_entry_refused_by_receiver` - Code R23. The receiving bank refused the + credit transfer. - `unauthorized_debit_to_consumer_account_using_corporate_sec_code` - Code R05. The receiving bank rejected because of an incorrect Standard Entry Class code. + Consumer accounts cannot be debited as `corporate_credit_or_debit` or + `corporate_trade_exchange`. - `corporate_customer_advised_not_authorized` - Code R29. The corporate customer at the receiving bank reversed the transfer. - `payment_stopped` - Code R08. The receiving bank stopped payment on this transfer. - - `non_transaction_account` - Code R20. The receiving bank account does not - perform transfers. + - `non_transaction_account` - Code R20. The account is not eligible for ACH, + such as a savings account with transaction limits. - `uncollected_funds` - Code R09. The receiving bank account does not have enough available balance for the transfer. - `routing_number_check_digit_error` - Code R28. The routing number is @@ -110,14 +114,13 @@ class ACHTransferReturnParams(TypedDict, total=False): - `customer_advised_unauthorized_improper_ineligible_or_incomplete` - Code R10. The customer at the receiving bank reversed the transfer. - `amount_field_error` - Code R19. The amount field is incorrect or too large. - - `authorization_revoked_by_customer` - Code R07. The customer at the receiving - institution informed their bank that they have revoked authorization for a - previously authorized transfer. + - `authorization_revoked_by_customer` - Code R07. The customer revoked their + authorization for a previously authorized transfer. - `invalid_ach_routing_number` - Code R13. The routing number is invalid. - `file_record_edit_criteria` - Code R17. The receiving bank is unable to process a field in the transfer. - - `enr_invalid_individual_name` - Code R45. The individual name field was - invalid. + - `enr_invalid_individual_name` - Code R45. A rare return reason. The individual + name field was invalid. - `returned_per_odfi_request` - Code R06. The originating financial institution asked for this transfer to be returned. The receiving bank is complying with the request. @@ -212,8 +215,8 @@ class ACHTransferReturnParams(TypedDict, total=False): a malformed credit entry. - `return_of_improper_debit_entry` - Code R35. A rare return reason. Return of a malformed debit entry. - - `return_of_xck_entry` - Code R33. A rare return reason. Return of a Destroyed - Check ("XKC") entry. + - `return_of_xck_entry` - Code R33. A rare return reason. Return of a destroyed + check ("XCK") entry. - `source_document_presented_for_payment` - Code R37. A rare return reason. The source document related to this ACH, usually an ACH check conversion, was presented to the bank. diff --git a/src/increase/types/simulations/card_authentication_challenge_attempts_params.py b/src/increase/types/simulations/card_authentication_challenge_attempts_params.py new file mode 100644 index 000000000..472611c19 --- /dev/null +++ b/src/increase/types/simulations/card_authentication_challenge_attempts_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["CardAuthenticationChallengeAttemptsParams"] + + +class CardAuthenticationChallengeAttemptsParams(TypedDict, total=False): + one_time_code: Required[str] + """The one-time code to be validated.""" diff --git a/src/increase/types/simulations/card_authentication_create_params.py b/src/increase/types/simulations/card_authentication_create_params.py new file mode 100644 index 000000000..2f559f1cf --- /dev/null +++ b/src/increase/types/simulations/card_authentication_create_params.py @@ -0,0 +1,50 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["CardAuthenticationCreateParams"] + + +class CardAuthenticationCreateParams(TypedDict, total=False): + card_id: Required[str] + """The identifier of the Card to be authorized.""" + + category: Literal["payment_authentication", "non_payment_authentication"] + """The category of the card authentication attempt. + + - `payment_authentication` - The authentication attempt is for a payment. + - `non_payment_authentication` - The authentication attempt is not for a + payment. + """ + + device_channel: Literal["app", "browser", "three_ds_requestor_initiated"] + """The device channel of the card authentication attempt. + + - `app` - The authentication attempt was made from an app. + - `browser` - The authentication attempt was made from a browser. + - `three_ds_requestor_initiated` - The authentication attempt was initiated by + the 3DS Requestor. + """ + + merchant_acceptor_id: str + """ + The merchant identifier (commonly abbreviated as MID) of the merchant the card + is transacting with. + """ + + merchant_category_code: str + """ + The Merchant Category Code (commonly abbreviated as MCC) of the merchant the + card is transacting with. + """ + + merchant_country: str + """The country the merchant resides in.""" + + merchant_name: str + """The name of the merchant""" + + purchase_amount: int + """The purchase amount in cents.""" diff --git a/src/increase/types/simulations/card_authorization_create_params.py b/src/increase/types/simulations/card_authorization_create_params.py index e66950f04..b65f4c06a 100644 --- a/src/increase/types/simulations/card_authorization_create_params.py +++ b/src/increase/types/simulations/card_authorization_create_params.py @@ -44,6 +44,7 @@ class CardAuthorizationCreateParams(TypedDict, total=False): "declined_by_stand_in_processing", "invalid_physical_card", "missing_original_authorization", + "invalid_cryptogram", "failed_3ds_authentication", "suspected_card_testing", "suspected_fraud", @@ -71,10 +72,12 @@ class CardAuthorizationCreateParams(TypedDict, total=False): - `webhook_timed_out` - Your application webhook did not respond without the required timeout. - `declined_by_stand_in_processing` - Declined by stand-in processing. - - `invalid_physical_card` - The card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The card read had an invalid CVV or dCVV. - `missing_original_authorization` - The original card authorization for this incremental authorization does not exist. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `failed_3ds_authentication` - The transaction was declined because the 3DS authentication failed. - `suspected_card_testing` - The transaction was suspected to be used by a card @@ -150,6 +153,7 @@ class NetworkDetailsVisa(TypedDict, total=False): stand_in_processing_reason: Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -160,8 +164,10 @@ class NetworkDetailsVisa(TypedDict, total=False): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason diff --git a/src/increase/types/simulations/card_balance_inquiry_create_params.py b/src/increase/types/simulations/card_balance_inquiry_create_params.py index 8ce3cf2b3..7c58c264e 100644 --- a/src/increase/types/simulations/card_balance_inquiry_create_params.py +++ b/src/increase/types/simulations/card_balance_inquiry_create_params.py @@ -32,6 +32,7 @@ class CardBalanceInquiryCreateParams(TypedDict, total=False): "declined_by_stand_in_processing", "invalid_physical_card", "missing_original_authorization", + "invalid_cryptogram", "failed_3ds_authentication", "suspected_card_testing", "suspected_fraud", @@ -59,10 +60,12 @@ class CardBalanceInquiryCreateParams(TypedDict, total=False): - `webhook_timed_out` - Your application webhook did not respond without the required timeout. - `declined_by_stand_in_processing` - Declined by stand-in processing. - - `invalid_physical_card` - The card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The card read had an invalid CVV or dCVV. - `missing_original_authorization` - The original card authorization for this incremental authorization does not exist. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `failed_3ds_authentication` - The transaction was declined because the 3DS authentication failed. - `suspected_card_testing` - The transaction was suspected to be used by a card @@ -132,6 +135,7 @@ class NetworkDetailsVisa(TypedDict, total=False): stand_in_processing_reason: Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -142,8 +146,10 @@ class NetworkDetailsVisa(TypedDict, total=False): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason diff --git a/src/increase/types/simulations/card_increment_create_params.py b/src/increase/types/simulations/card_increment_create_params.py index 85f2aafc5..508c252e7 100644 --- a/src/increase/types/simulations/card_increment_create_params.py +++ b/src/increase/types/simulations/card_increment_create_params.py @@ -14,7 +14,7 @@ class CardIncrementCreateParams(TypedDict, total=False): """ card_payment_id: Required[str] - """The identifier of the Card Payment to create a increment on.""" + """The identifier of the Card Payment to create an increment on.""" event_subscription_id: str """The identifier of the Event Subscription to use. diff --git a/src/increase/types/simulations/check_deposit_adjustment_params.py b/src/increase/types/simulations/check_deposit_adjustment_params.py new file mode 100644 index 000000000..7627917c0 --- /dev/null +++ b/src/increase/types/simulations/check_deposit_adjustment_params.py @@ -0,0 +1,35 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["CheckDepositAdjustmentParams"] + + +class CheckDepositAdjustmentParams(TypedDict, total=False): + amount: int + """ + The adjustment amount in the minor unit of the Check Deposit's currency (e.g., + cents). A negative amount means that the funds are being clawed back by the + other bank and is a debit to your account. Defaults to the negative of the Check + Deposit amount. + """ + + reason: Literal["late_return", "wrong_payee_credit", "adjusted_amount", "non_conforming_item", "paid"] + """The reason for the adjustment. + + Defaults to `non_conforming_item`, which is often used for a low quality image + that the recipient wasn't able to handle. + + - `late_return` - The return was initiated too late and the receiving + institution has responded with a Late Return Claim. + - `wrong_payee_credit` - The check was deposited to the wrong payee and the + depositing institution has reimbursed the funds with a Wrong Payee Credit. + - `adjusted_amount` - The check was deposited with a different amount than what + was written on the check. + - `non_conforming_item` - The recipient was not able to process the check. This + usually happens for e.g., low quality images. + - `paid` - The check has already been deposited elsewhere and so this is a + duplicate. + """ diff --git a/src/increase/types/simulations/check_deposit_submit_params.py b/src/increase/types/simulations/check_deposit_submit_params.py new file mode 100644 index 000000000..82abf0a46 --- /dev/null +++ b/src/increase/types/simulations/check_deposit_submit_params.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["CheckDepositSubmitParams", "Scan"] + + +class CheckDepositSubmitParams(TypedDict, total=False): + scan: Scan + """If set, the simulation will use these values for the check's scanned MICR data.""" + + +class Scan(TypedDict, total=False): + """If set, the simulation will use these values for the check's scanned MICR data.""" + + account_number: Required[str] + """The account number to be returned in the check deposit's scan data.""" + + routing_number: Required[str] + """The routing number to be returned in the check deposit's scan data.""" + + auxiliary_on_us: str + """The auxiliary on-us data to be returned in the check deposit's scan data.""" diff --git a/src/increase/types/simulations/inbound_check_deposit_adjustment_params.py b/src/increase/types/simulations/inbound_check_deposit_adjustment_params.py new file mode 100644 index 000000000..80357357e --- /dev/null +++ b/src/increase/types/simulations/inbound_check_deposit_adjustment_params.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["InboundCheckDepositAdjustmentParams"] + + +class InboundCheckDepositAdjustmentParams(TypedDict, total=False): + amount: int + """The adjustment amount in cents. + + Defaults to the amount of the Inbound Check Deposit. + """ + + reason: Literal["late_return", "wrong_payee_credit", "adjusted_amount", "non_conforming_item", "paid"] + """The reason for the adjustment. Defaults to `wrong_payee_credit`. + + - `late_return` - The return was initiated too late and the receiving + institution has responded with a Late Return Claim. + - `wrong_payee_credit` - The check was deposited to the wrong payee and the + depositing institution has reimbursed the funds with a Wrong Payee Credit. + - `adjusted_amount` - The check was deposited with a different amount than what + was written on the check. + - `non_conforming_item` - The recipient was not able to process the check. This + usually happens for e.g., low quality images. + - `paid` - The check has already been deposited elsewhere and so this is a + duplicate. + """ diff --git a/src/increase/types/simulations/program_create_params.py b/src/increase/types/simulations/program_create_params.py index 7153e2292..0985e9ca9 100644 --- a/src/increase/types/simulations/program_create_params.py +++ b/src/increase/types/simulations/program_create_params.py @@ -11,23 +11,17 @@ class ProgramCreateParams(TypedDict, total=False): name: Required[str] """The name of the program being added.""" - bank: Literal[ - "blue_ridge_bank", - "core_bank", - "first_internet_bank", - "global_innovations_bank", - "grasshopper_bank", - "twin_city_bank", - ] + bank: Literal["core_bank", "first_internet_bank", "grasshopper_bank", "twin_city_bank"] """The bank for the program's accounts, defaults to First Internet Bank. - - `blue_ridge_bank` - Blue Ridge Bank, N.A. - `core_bank` - Core Bank - `first_internet_bank` - First Internet Bank of Indiana - - `global_innovations_bank` - Global Innovations Bank - `grasshopper_bank` - Grasshopper Bank - `twin_city_bank` - Twin City Bank """ + lending_maximum_extendable_credit: int + """The maximum extendable credit of the program being added.""" + reserve_account_id: str """The identifier of the Account the Program should be added to is for.""" diff --git a/src/increase/types/swift_transfer.py b/src/increase/types/swift_transfer.py new file mode 100644 index 000000000..5344a4452 --- /dev/null +++ b/src/increase/types/swift_transfer.py @@ -0,0 +1,232 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = [ + "SwiftTransfer", + "CreatedBy", + "CreatedByAPIKey", + "CreatedByOAuthApplication", + "CreatedByUser", + "CreditorAddress", + "DebtorAddress", +] + + +class CreatedByAPIKey(BaseModel): + """If present, details about the API key that created the transfer.""" + + description: Optional[str] = None + """The description set for the API key when it was created.""" + + +class CreatedByOAuthApplication(BaseModel): + """If present, details about the OAuth Application that created the transfer.""" + + name: str + """The name of the OAuth Application.""" + + +class CreatedByUser(BaseModel): + """If present, details about the User that created the transfer.""" + + email: str + """The email address of the User.""" + + +class CreatedBy(BaseModel): + """What object created the transfer, either via the API or the dashboard.""" + + category: Literal["api_key", "oauth_application", "user"] + """The type of object that created this transfer. + + - `api_key` - An API key. Details will be under the `api_key` object. + - `oauth_application` - An OAuth application you connected to Increase. Details + will be under the `oauth_application` object. + - `user` - A User in the Increase dashboard. Details will be under the `user` + object. + """ + + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + + oauth_application: Optional[CreatedByOAuthApplication] = None + """If present, details about the OAuth Application that created the transfer.""" + + user: Optional[CreatedByUser] = None + """If present, details about the User that created the transfer.""" + + +class CreditorAddress(BaseModel): + """The creditor's address.""" + + city: Optional[str] = None + """The city, district, town, or village of the address.""" + + country: str + """ + The two-letter + [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code for + the country of the address. + """ + + line1: str + """The first line of the address.""" + + line2: Optional[str] = None + """The second line of the address.""" + + postal_code: Optional[str] = None + """The ZIP or postal code of the address.""" + + state: Optional[str] = None + """The state, province, or region of the address. Required in certain countries.""" + + +class DebtorAddress(BaseModel): + """The debtor's address.""" + + city: Optional[str] = None + """The city, district, town, or village of the address.""" + + country: str + """ + The two-letter + [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code for + the country of the address. + """ + + line1: str + """The first line of the address.""" + + line2: Optional[str] = None + """The second line of the address.""" + + postal_code: Optional[str] = None + """The ZIP or postal code of the address.""" + + state: Optional[str] = None + """The state, province, or region of the address. Required in certain countries.""" + + +class SwiftTransfer(BaseModel): + """Swift Transfers send funds internationally.""" + + id: str + """The Swift transfer's identifier.""" + + account_id: str + """The Account to which the transfer belongs.""" + + account_number: str + """The creditor's account number.""" + + amount: int + """The transfer amount in USD cents.""" + + bank_identification_code: str + """The bank identification code (BIC) of the creditor.""" + + created_at: datetime + """ + The [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date and time at which + the transfer was created. + """ + + created_by: CreatedBy + """What object created the transfer, either via the API or the dashboard.""" + + creditor_address: CreditorAddress + """The creditor's address.""" + + creditor_name: str + """The creditor's name.""" + + debtor_address: DebtorAddress + """The debtor's address.""" + + debtor_name: str + """The debtor's name.""" + + idempotency_key: Optional[str] = None + """The idempotency key you chose for this object. + + This value is unique across Increase and is used to ensure that a request is + only processed once. Learn more about + [idempotency](https://increase.com/documentation/idempotency-keys). + """ + + instructed_amount: int + """ + The amount that was instructed to be transferred in minor units of the + `instructed_currency`. + """ + + instructed_currency: Literal["USD"] + """ + The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code of the + instructed amount. + + - `USD` - United States Dollar + """ + + pending_transaction_id: Optional[str] = None + """The ID for the pending transaction representing the transfer.""" + + routing_number: Optional[str] = None + """The creditor's bank account routing or transit number. + + Required in certain countries. + """ + + source_account_number_id: str + """The Account Number included in the transfer as the debtor's account number.""" + + status: Literal[ + "pending_approval", + "canceled", + "pending_reviewing", + "requires_attention", + "pending_initiating", + "initiated", + "rejected", + "returned", + ] + """The lifecycle status of the transfer. + + - `pending_approval` - The transfer is pending approval. + - `canceled` - The transfer has been canceled. + - `pending_reviewing` - The transfer is pending review by Increase. + - `requires_attention` - The transfer requires attention from an Increase + operator. + - `pending_initiating` - The transfer is pending initiation. + - `initiated` - The transfer has been initiated. + - `rejected` - The transfer has been rejected by Increase. + - `returned` - The transfer has been returned. + """ + + transaction_id: Optional[str] = None + """The ID for the transaction funding the transfer. + + This will be populated after the transfer is initiated. + """ + + type: Literal["swift_transfer"] + """A constant representing the object's type. + + For this resource it will always be `swift_transfer`. + """ + + unique_end_to_end_transaction_reference: str + """ + The Unique End-to-end Transaction Reference + ([UETR](https://www.swift.com/payments/what-unique-end-end-transaction-reference-uetr)) + for the transfer. + """ + + unstructured_remittance_information: str + """The unstructured remittance information that was included with the transfer.""" diff --git a/src/increase/types/swift_transfer_create_params.py b/src/increase/types/swift_transfer_create_params.py new file mode 100644 index 000000000..2a37c670d --- /dev/null +++ b/src/increase/types/swift_transfer_create_params.py @@ -0,0 +1,113 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["SwiftTransferCreateParams", "CreditorAddress", "DebtorAddress"] + + +class SwiftTransferCreateParams(TypedDict, total=False): + account_id: Required[str] + """The identifier for the account that will send the transfer.""" + + account_number: Required[str] + """The creditor's account number.""" + + bank_identification_code: Required[str] + """The bank identification code (BIC) of the creditor. + + If it ends with the three-character branch code, this must be 11 characters + long. Otherwise this must be 8 characters and the branch code will be assumed to + be `XXX`. + """ + + creditor_address: Required[CreditorAddress] + """The creditor's address.""" + + creditor_name: Required[str] + """The creditor's name.""" + + debtor_address: Required[DebtorAddress] + """The debtor's address.""" + + debtor_name: Required[str] + """The debtor's name.""" + + instructed_amount: Required[int] + """The amount, in minor units of `instructed_currency`, to send to the creditor.""" + + instructed_currency: Required[Literal["USD"]] + """ + The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code of the + instructed amount. + + - `USD` - United States Dollar + """ + + source_account_number_id: Required[str] + """The Account Number to include in the transfer as the debtor's account number.""" + + unstructured_remittance_information: Required[str] + """Unstructured remittance information to include in the transfer.""" + + require_approval: bool + """Whether the transfer requires explicit approval via the dashboard or API.""" + + routing_number: str + """The creditor's bank account routing or transit number. + + Required in certain countries. + """ + + +class CreditorAddress(TypedDict, total=False): + """The creditor's address.""" + + city: Required[str] + """The city, district, town, or village of the address.""" + + country: Required[str] + """ + The two-letter + [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code for + the country of the address. + """ + + line1: Required[str] + """The first line of the address. This is usually the street number and street.""" + + line2: str + """The second line of the address. This might be the floor or room number.""" + + postal_code: str + """The ZIP or postal code of the address. Required in certain countries.""" + + state: str + """The state, province, or region of the address. Required in certain countries.""" + + +class DebtorAddress(TypedDict, total=False): + """The debtor's address.""" + + city: Required[str] + """The city, district, town, or village of the address.""" + + country: Required[str] + """ + The two-letter + [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code for + the country of the address. + """ + + line1: Required[str] + """The first line of the address. This is usually the street number and street.""" + + line2: str + """The second line of the address. This might be the floor or room number.""" + + postal_code: str + """The ZIP or postal code of the address. Required in certain countries.""" + + state: str + """The state, province, or region of the address. Required in certain countries.""" diff --git a/src/increase/types/swift_transfer_list_params.py b/src/increase/types/swift_transfer_list_params.py new file mode 100644 index 000000000..15f14bd69 --- /dev/null +++ b/src/increase/types/swift_transfer_list_params.py @@ -0,0 +1,87 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union +from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["SwiftTransferListParams", "CreatedAt", "Status"] + + +class SwiftTransferListParams(TypedDict, total=False): + account_id: str + """Filter Swift Transfers to those that originated from the specified Account.""" + + created_at: CreatedAt + + cursor: str + """Return the page of entries after this one.""" + + idempotency_key: str + """ + Filter records to the one with the specified `idempotency_key` you chose for + that object. This value is unique across Increase and is used to ensure that a + request is only processed once. Learn more about + [idempotency](https://increase.com/documentation/idempotency-keys). + """ + + limit: int + """Limit the size of the list that is returned. + + The default (and maximum) is 100 objects. + """ + + status: Status + + +class CreatedAt(TypedDict, total=False): + after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """ + Return results after this [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) + timestamp. + """ + + before: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """ + Return results before this [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) + timestamp. + """ + + on_or_after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """ + Return results on or after this + [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) timestamp. + """ + + on_or_before: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """ + Return results on or before this + [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) timestamp. + """ + + +_StatusReservedKeywords = TypedDict( + "_StatusReservedKeywords", + { + "in": List[ + Literal[ + "pending_approval", + "canceled", + "pending_reviewing", + "requires_attention", + "pending_initiating", + "initiated", + "rejected", + "returned", + ] + ], + }, + total=False, +) + + +class Status(_StatusReservedKeywords, total=False): + pass diff --git a/src/increase/types/transaction.py b/src/increase/types/transaction.py index 05c14c2b5..b0c8301c9 100644 --- a/src/increase/types/transaction.py +++ b/src/increase/types/transaction.py @@ -16,6 +16,8 @@ "SourceACHTransferIntention", "SourceACHTransferRejection", "SourceACHTransferReturn", + "SourceBlockchainOfframpTransferSettlement", + "SourceBlockchainOnrampTransferIntention", "SourceCardDisputeAcceptance", "SourceCardDisputeFinancial", "SourceCardDisputeFinancialVisa", @@ -39,6 +41,7 @@ "SourceCardFinancialVerification", "SourceCardFinancialVerificationCardVerificationCode", "SourceCardFinancialVerificationCardholderAddress", + "SourceCardFinancialVerificationCardholderName", "SourceCardPushTransferAcceptance", "SourceCardRefund", "SourceCardRefundCashback", @@ -320,24 +323,28 @@ class SourceACHTransferReturn(BaseModel): This reason code is sent by the receiving bank back to Increase. - `insufficient_fund` - Code R01. Insufficient funds in the receiving account. - Sometimes abbreviated to NSF. + Sometimes abbreviated to "NSF." - `no_account` - Code R03. The account does not exist or the receiving bank was unable to locate it. - `account_closed` - Code R02. The account is closed at the receiving bank. - `invalid_account_number_structure` - Code R04. The account number is invalid at the receiving bank. - - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. The account - at the receiving bank was frozen per the Office of Foreign Assets Control. - - `credit_entry_refused_by_receiver` - Code R23. The receiving bank account - refused a credit transfer. + - `account_frozen_entry_returned_per_ofac_instruction` - Code R16. This return + code has two separate meanings. (1) The receiving bank froze the account or + (2) the Office of Foreign Assets Control (OFAC) instructed the receiving bank + to return the entry. + - `credit_entry_refused_by_receiver` - Code R23. The receiving bank refused the + credit transfer. - `unauthorized_debit_to_consumer_account_using_corporate_sec_code` - Code R05. The receiving bank rejected because of an incorrect Standard Entry Class code. + Consumer accounts cannot be debited as `corporate_credit_or_debit` or + `corporate_trade_exchange`. - `corporate_customer_advised_not_authorized` - Code R29. The corporate customer at the receiving bank reversed the transfer. - `payment_stopped` - Code R08. The receiving bank stopped payment on this transfer. - - `non_transaction_account` - Code R20. The receiving bank account does not - perform transfers. + - `non_transaction_account` - Code R20. The account is not eligible for ACH, + such as a savings account with transaction limits. - `uncollected_funds` - Code R09. The receiving bank account does not have enough available balance for the transfer. - `routing_number_check_digit_error` - Code R28. The routing number is @@ -345,14 +352,13 @@ class SourceACHTransferReturn(BaseModel): - `customer_advised_unauthorized_improper_ineligible_or_incomplete` - Code R10. The customer at the receiving bank reversed the transfer. - `amount_field_error` - Code R19. The amount field is incorrect or too large. - - `authorization_revoked_by_customer` - Code R07. The customer at the receiving - institution informed their bank that they have revoked authorization for a - previously authorized transfer. + - `authorization_revoked_by_customer` - Code R07. The customer revoked their + authorization for a previously authorized transfer. - `invalid_ach_routing_number` - Code R13. The routing number is invalid. - `file_record_edit_criteria` - Code R17. The receiving bank is unable to process a field in the transfer. - - `enr_invalid_individual_name` - Code R45. The individual name field was - invalid. + - `enr_invalid_individual_name` - Code R45. A rare return reason. The individual + name field was invalid. - `returned_per_odfi_request` - Code R06. The originating financial institution asked for this transfer to be returned. The receiving bank is complying with the request. @@ -447,8 +453,8 @@ class SourceACHTransferReturn(BaseModel): a malformed credit entry. - `return_of_improper_debit_entry` - Code R35. A rare return reason. Return of a malformed debit entry. - - `return_of_xck_entry` - Code R33. A rare return reason. Return of a Destroyed - Check ("XKC") entry. + - `return_of_xck_entry` - Code R33. A rare return reason. Return of a destroyed + check ("XCK") entry. - `source_document_presented_for_payment` - Code R37. A rare return reason. The source document related to this ACH, usually an ACH check conversion, was presented to the bank. @@ -495,6 +501,58 @@ def __getattr__(self, attr: str) -> object: ... __pydantic_extra__: Dict[str, object] +class SourceBlockchainOfframpTransferSettlement(BaseModel): + """A Blockchain Off-Ramp Transfer Settlement object. + + This field will be present in the JSON response if and only if `category` is equal to `blockchain_offramp_transfer_settlement`. + """ + + source_blockchain_address_id: str + """The identifier of the Blockchain Address the funds were received at.""" + + transfer_id: str + """ + The identifier of the Blockchain Off-Ramp Transfer that led to this Transaction. + """ + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] + + +class SourceBlockchainOnrampTransferIntention(BaseModel): + """A Blockchain On-Ramp Transfer Intention object. + + This field will be present in the JSON response if and only if `category` is equal to `blockchain_onramp_transfer_intention`. + """ + + destination_blockchain_address: str + """The blockchain address the funds were sent to.""" + + transfer_id: str + """The identifier of the Blockchain On-Ramp Transfer that led to this Transaction.""" + + if TYPE_CHECKING: + # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a + # value to this field, so for compatibility we avoid doing it at runtime. + __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride] + + # Stub to indicate that arbitrary properties are accepted. + # To access properties that are not valid identifiers you can use `getattr`, e.g. + # `getattr(obj, '$type')` + def __getattr__(self, attr: str) -> object: ... + else: + __pydantic_extra__: Dict[str, object] + + class SourceCardDisputeAcceptance(BaseModel): """A Legacy Card Dispute Acceptance object. @@ -935,6 +993,7 @@ class SourceCardFinancialNetworkDetailsVisa(BaseModel): Literal[ "issuer_error", "invalid_physical_card", + "invalid_cryptogram", "invalid_cardholder_authentication_verification_value", "internal_visa_error", "merchant_transaction_advisory_service_authentication_required", @@ -949,8 +1008,10 @@ class SourceCardFinancialNetworkDetailsVisa(BaseModel): - `issuer_error` - Increase failed to process the authorization in a timely manner. - - `invalid_physical_card` - The physical card read had an invalid CVV, dCVV, or - authorization request cryptogram. + - `invalid_physical_card` - The physical card read had an invalid CVV or dCVV. + - `invalid_cryptogram` - The card's authorization request cryptogram was + invalid. The cryptogram can be from a physical card or a Digital Wallet Token + purchase. - `invalid_cardholder_authentication_verification_value` - The 3DS cardholder authentication verification value was invalid. - `internal_visa_error` - An internal Visa error occurred. Visa uses this reason @@ -966,6 +1027,41 @@ class SourceCardFinancialNetworkDetailsVisa(BaseModel): - `other` - An unspecific reason for stand-in processing. """ + terminal_entry_capability: Optional[ + Literal[ + "unknown", + "terminal_not_used", + "magnetic_stripe", + "barcode", + "optical_character_recognition", + "chip_or_contactless", + "contactless_only", + "no_capability", + ] + ] = None + """The capability of the terminal being used to read the card. + + Shows whether a terminal can e.g., accept chip cards or if it only supports + magnetic stripe reads. This reflects the highest capability of the terminal — + for example, a terminal that supports both chip and magnetic stripe will be + identified as chip-capable. + + - `unknown` - Unknown + - `terminal_not_used` - No terminal was used for this transaction. + - `magnetic_stripe` - The terminal can only read magnetic stripes and does not + have chip or contactless reading capability. + - `barcode` - The terminal can only read barcodes. + - `optical_character_recognition` - The terminal can only read cards via Optical + Character Recognition. + - `chip_or_contactless` - The terminal supports contact chip cards and can also + read the magnetic stripe. If contact chip is supported, this value is used + regardless of whether contactless is also supported. + - `contactless_only` - The terminal supports contactless reads but does not + support contact chip. Only used when the terminal lacks contact chip + capability. + - `no_capability` - The terminal has no card reading capability. + """ + class SourceCardFinancialNetworkDetails(BaseModel): """Fields specific to the `network`.""" @@ -1071,6 +1167,19 @@ class SourceCardFinancialVerificationCardholderAddress(BaseModel): """ +class SourceCardFinancialVerificationCardholderName(BaseModel): + """Cardholder name provided in the authorization request.""" + + provided_first_name: Optional[str] = None + """The first name provided for verification in the authorization request.""" + + provided_last_name: Optional[str] = None + """The last name provided for verification in the authorization request.""" + + provided_middle_name: Optional[str] = None + """The middle name provided for verification in the authorization request.""" + + class SourceCardFinancialVerification(BaseModel): """Fields related to verification of cardholder-provided values.""" @@ -1086,11 +1195,14 @@ class SourceCardFinancialVerification(BaseModel): we verified it against. """ + cardholder_name: Optional[SourceCardFinancialVerificationCardholderName] = None + """Cardholder name provided in the authorization request.""" + class SourceCardFinancial(BaseModel): """A Card Financial object. - This field will be present in the JSON response if and only if `category` is equal to `card_financial`. Card Financials are temporary holds placed on a customers funds with the intent to later clear a transaction. + This field will be present in the JSON response if and only if `category` is equal to `card_financial`. Card Financials are temporary holds placed on a customer's funds with the intent to later clear a transaction. """ id: str @@ -1328,7 +1440,7 @@ class SourceCardRefundCashback(BaseModel): class SourceCardRefundInterchange(BaseModel): - """Interchange assessed as a part of this transaciton.""" + """Interchange assessed as a part of this transaction.""" amount: str """ @@ -1797,7 +1909,7 @@ class SourceCardRefundPurchaseDetails(BaseModel): class SourceCardRefund(BaseModel): """A Card Refund object. - This field will be present in the JSON response if and only if `category` is equal to `card_refund`. Card Refunds move money back to the cardholder. While they are usually connected to a Card Settlement an acquirer can also refund money directly to a card without relation to a transaction. + This field will be present in the JSON response if and only if `category` is equal to `card_refund`. Card Refunds move money back to the cardholder. While they are usually connected to a Card Settlement, an acquirer can also refund money directly to a card without relation to a transaction. """ id: str @@ -1827,7 +1939,7 @@ class SourceCardRefund(BaseModel): """ interchange: Optional[SourceCardRefundInterchange] = None - """Interchange assessed as a part of this transaciton.""" + """Interchange assessed as a part of this transaction.""" merchant_acceptor_id: str """ @@ -2425,7 +2537,7 @@ class SourceCardSettlementPurchaseDetails(BaseModel): class SourceCardSettlementSurcharge(BaseModel): """Surcharge amount details, if applicable. - The amount is positive if the surcharge is added to to the overall transaction amount (surcharge), and negative if the surcharge is deducted from the overall transaction amount (discount). + The amount is positive if the surcharge is added to the overall transaction amount (surcharge), and negative if the surcharge is deducted from the overall transaction amount (discount). """ amount: int @@ -2536,7 +2648,7 @@ class SourceCardSettlement(BaseModel): surcharge: Optional[SourceCardSettlementSurcharge] = None """Surcharge amount details, if applicable. - The amount is positive if the surcharge is added to to the overall transaction + The amount is positive if the surcharge is added to the overall transaction amount (surcharge), and negative if the surcharge is deducted from the overall transaction amount (discount). """ @@ -3412,6 +3524,7 @@ class SourceInternalSource(BaseModel): "error", "error_correction", "fees", + "general_ledger_transfer", "interest", "negative_balance_forgiveness", "sample_funds", @@ -3434,6 +3547,7 @@ class SourceInternalSource(BaseModel): - `error` - Error - `error_correction` - Error correction - `fees` - Fees + - `general_ledger_transfer` - General ledger transfer - `interest` - Interest - `negative_balance_forgiveness` - Negative balance forgiveness - `sample_funds` - Sample funds @@ -3600,126 +3714,6 @@ class Source(BaseModel): This is an object giving more details on the network-level event that caused the Transaction. Note that for backwards compatibility reasons, additional undocumented keys may appear in this object. These should be treated as deprecated and will be removed in the future. """ - account_revenue_payment: Optional[SourceAccountRevenuePayment] = None - """An Account Revenue Payment object. - - This field will be present in the JSON response if and only if `category` is - equal to `account_revenue_payment`. An Account Revenue Payment represents a - payment made to an account from the bank. Account revenue is a type of - non-interest income. - """ - - account_transfer_intention: Optional[SourceAccountTransferIntention] = None - """An Account Transfer Intention object. - - This field will be present in the JSON response if and only if `category` is - equal to `account_transfer_intention`. Two Account Transfer Intentions are - created from each Account Transfer. One decrements the source account, and the - other increments the destination account. - """ - - ach_transfer_intention: Optional[SourceACHTransferIntention] = None - """An ACH Transfer Intention object. - - This field will be present in the JSON response if and only if `category` is - equal to `ach_transfer_intention`. An ACH Transfer Intention is created from an - ACH Transfer. It reflects the intention to move money into or out of an Increase - account via the ACH network. - """ - - ach_transfer_rejection: Optional[SourceACHTransferRejection] = None - """An ACH Transfer Rejection object. - - This field will be present in the JSON response if and only if `category` is - equal to `ach_transfer_rejection`. An ACH Transfer Rejection is created when an - ACH Transfer is rejected by Increase. It offsets the ACH Transfer Intention. - These rejections are rare. - """ - - ach_transfer_return: Optional[SourceACHTransferReturn] = None - """An ACH Transfer Return object. - - This field will be present in the JSON response if and only if `category` is - equal to `ach_transfer_return`. An ACH Transfer Return is created when an ACH - Transfer is returned by the receiving bank. It offsets the ACH Transfer - Intention. ACH Transfer Returns usually occur within the first two business days - after the transfer is initiated, but can occur much later. - """ - - card_dispute_acceptance: Optional[SourceCardDisputeAcceptance] = None - """A Legacy Card Dispute Acceptance object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_dispute_acceptance`. Contains the details of a successful Card - Dispute. - """ - - card_dispute_financial: Optional[SourceCardDisputeFinancial] = None - """A Card Dispute Financial object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_dispute_financial`. Financial event related to a Card Dispute. - """ - - card_dispute_loss: Optional[SourceCardDisputeLoss] = None - """A Legacy Card Dispute Loss object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_dispute_loss`. Contains the details of a lost Card Dispute. - """ - - card_financial: Optional[SourceCardFinancial] = None - """A Card Financial object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_financial`. Card Financials are temporary holds placed on a - customers funds with the intent to later clear a transaction. - """ - - card_push_transfer_acceptance: Optional[SourceCardPushTransferAcceptance] = None - """A Card Push Transfer Acceptance object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_push_transfer_acceptance`. A Card Push Transfer Acceptance is - created when an Outbound Card Push Transfer sent from Increase is accepted by - the receiving bank. - """ - - card_refund: Optional[SourceCardRefund] = None - """A Card Refund object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_refund`. Card Refunds move money back to the cardholder. While - they are usually connected to a Card Settlement an acquirer can also refund - money directly to a card without relation to a transaction. - """ - - card_revenue_payment: Optional[SourceCardRevenuePayment] = None - """A Card Revenue Payment object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_revenue_payment`. Card Revenue Payments reflect earnings from - fees on card transactions. - """ - - card_settlement: Optional[SourceCardSettlement] = None - """A Card Settlement object. - - This field will be present in the JSON response if and only if `category` is - equal to `card_settlement`. Card Settlements are card transactions that have - cleared and settled. While a settlement is usually preceded by an authorization, - an acquirer can also directly clear a transaction without first authorizing it. - """ - - cashback_payment: Optional[SourceCashbackPayment] = None - """A Cashback Payment object. - - This field will be present in the JSON response if and only if `category` is - equal to `cashback_payment`. A Cashback Payment represents the cashback paid to - a cardholder for a given period. Cashback is usually paid monthly for the prior - month's transactions. - """ - category: Literal[ "account_transfer_intention", "ach_transfer_intention", @@ -3756,6 +3750,8 @@ class Source(BaseModel): "swift_transfer_return", "card_push_transfer_acceptance", "account_revenue_payment", + "blockchain_onramp_transfer_intention", + "blockchain_offramp_transfer_settlement", "other", ] """The type of the resource. @@ -3835,9 +3831,149 @@ class Source(BaseModel): be under the `card_push_transfer_acceptance` object. - `account_revenue_payment` - Account Revenue Payment: details will be under the `account_revenue_payment` object. + - `blockchain_onramp_transfer_intention` - Blockchain On-Ramp Transfer + Intention: details will be under the `blockchain_onramp_transfer_intention` + object. + - `blockchain_offramp_transfer_settlement` - Blockchain Off-Ramp Transfer + Settlement: details will be under the `blockchain_offramp_transfer_settlement` + object. - `other` - The Transaction was made for an undocumented or deprecated reason. """ + account_revenue_payment: Optional[SourceAccountRevenuePayment] = None + """An Account Revenue Payment object. + + This field will be present in the JSON response if and only if `category` is + equal to `account_revenue_payment`. An Account Revenue Payment represents a + payment made to an account from the bank. Account revenue is a type of + non-interest income. + """ + + account_transfer_intention: Optional[SourceAccountTransferIntention] = None + """An Account Transfer Intention object. + + This field will be present in the JSON response if and only if `category` is + equal to `account_transfer_intention`. Two Account Transfer Intentions are + created from each Account Transfer. One decrements the source account, and the + other increments the destination account. + """ + + ach_transfer_intention: Optional[SourceACHTransferIntention] = None + """An ACH Transfer Intention object. + + This field will be present in the JSON response if and only if `category` is + equal to `ach_transfer_intention`. An ACH Transfer Intention is created from an + ACH Transfer. It reflects the intention to move money into or out of an Increase + account via the ACH network. + """ + + ach_transfer_rejection: Optional[SourceACHTransferRejection] = None + """An ACH Transfer Rejection object. + + This field will be present in the JSON response if and only if `category` is + equal to `ach_transfer_rejection`. An ACH Transfer Rejection is created when an + ACH Transfer is rejected by Increase. It offsets the ACH Transfer Intention. + These rejections are rare. + """ + + ach_transfer_return: Optional[SourceACHTransferReturn] = None + """An ACH Transfer Return object. + + This field will be present in the JSON response if and only if `category` is + equal to `ach_transfer_return`. An ACH Transfer Return is created when an ACH + Transfer is returned by the receiving bank. It offsets the ACH Transfer + Intention. ACH Transfer Returns usually occur within the first two business days + after the transfer is initiated, but can occur much later. + """ + + blockchain_offramp_transfer_settlement: Optional[SourceBlockchainOfframpTransferSettlement] = None + """A Blockchain Off-Ramp Transfer Settlement object. + + This field will be present in the JSON response if and only if `category` is + equal to `blockchain_offramp_transfer_settlement`. + """ + + blockchain_onramp_transfer_intention: Optional[SourceBlockchainOnrampTransferIntention] = None + """A Blockchain On-Ramp Transfer Intention object. + + This field will be present in the JSON response if and only if `category` is + equal to `blockchain_onramp_transfer_intention`. + """ + + card_dispute_acceptance: Optional[SourceCardDisputeAcceptance] = None + """A Legacy Card Dispute Acceptance object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_dispute_acceptance`. Contains the details of a successful Card + Dispute. + """ + + card_dispute_financial: Optional[SourceCardDisputeFinancial] = None + """A Card Dispute Financial object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_dispute_financial`. Financial event related to a Card Dispute. + """ + + card_dispute_loss: Optional[SourceCardDisputeLoss] = None + """A Legacy Card Dispute Loss object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_dispute_loss`. Contains the details of a lost Card Dispute. + """ + + card_financial: Optional[SourceCardFinancial] = None + """A Card Financial object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_financial`. Card Financials are temporary holds placed on a + customer's funds with the intent to later clear a transaction. + """ + + card_push_transfer_acceptance: Optional[SourceCardPushTransferAcceptance] = None + """A Card Push Transfer Acceptance object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_push_transfer_acceptance`. A Card Push Transfer Acceptance is + created when an Outbound Card Push Transfer sent from Increase is accepted by + the receiving bank. + """ + + card_refund: Optional[SourceCardRefund] = None + """A Card Refund object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_refund`. Card Refunds move money back to the cardholder. While + they are usually connected to a Card Settlement, an acquirer can also refund + money directly to a card without relation to a transaction. + """ + + card_revenue_payment: Optional[SourceCardRevenuePayment] = None + """A Card Revenue Payment object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_revenue_payment`. Card Revenue Payments reflect earnings from + fees on card transactions. + """ + + card_settlement: Optional[SourceCardSettlement] = None + """A Card Settlement object. + + This field will be present in the JSON response if and only if `category` is + equal to `card_settlement`. Card Settlements are card transactions that have + cleared and settled. While a settlement is usually preceded by an authorization, + an acquirer can also directly clear a transaction without first authorizing it. + """ + + cashback_payment: Optional[SourceCashbackPayment] = None + """A Cashback Payment object. + + This field will be present in the JSON response if and only if `category` is + equal to `cashback_payment`. A Cashback Payment represents the cashback paid to + a cardholder for a given period. Cashback is usually paid monthly for the prior + month's transactions. + """ + check_deposit_acceptance: Optional[SourceCheckDepositAcceptance] = None """A Check Deposit Acceptance object. diff --git a/src/increase/types/transaction_list_params.py b/src/increase/types/transaction_list_params.py index 4af4a7d26..25c686b9e 100644 --- a/src/increase/types/transaction_list_params.py +++ b/src/increase/types/transaction_list_params.py @@ -75,6 +75,8 @@ class TransactionListParams(TypedDict, total=False): "swift_transfer_return", "card_push_transfer_acceptance", "account_revenue_payment", + "blockchain_onramp_transfer_intention", + "blockchain_offramp_transfer_settlement", "other", ] ], diff --git a/src/increase/types/unwrap_webhook_event.py b/src/increase/types/unwrap_webhook_event.py new file mode 100644 index 000000000..536c8303f --- /dev/null +++ b/src/increase/types/unwrap_webhook_event.py @@ -0,0 +1,319 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["UnwrapWebhookEvent"] + + +class UnwrapWebhookEvent(BaseModel): + """Events are records of things that happened to objects at Increase. + + Events are accessible via the List Events endpoint and can be delivered to your application via webhooks. For more information, see our [webhooks guide](https://increase.com/documentation/webhooks). + """ + + id: str + """The Event identifier.""" + + associated_object_id: str + """The identifier of the object that generated this Event.""" + + associated_object_type: str + """The type of the object that generated this Event.""" + + category: Literal[ + "account.created", + "account.updated", + "account_number.created", + "account_number.updated", + "account_statement.created", + "account_transfer.created", + "account_transfer.updated", + "ach_prenotification.created", + "ach_prenotification.updated", + "ach_transfer.created", + "ach_transfer.updated", + "blockchain_address.created", + "blockchain_address.updated", + "blockchain_offramp_transfer.created", + "blockchain_offramp_transfer.updated", + "blockchain_onramp_transfer.created", + "blockchain_onramp_transfer.updated", + "bookkeeping_account.created", + "bookkeeping_account.updated", + "bookkeeping_entry_set.updated", + "card.created", + "card.updated", + "card_payment.created", + "card_payment.updated", + "card_profile.created", + "card_profile.updated", + "card_dispute.created", + "card_dispute.updated", + "check_deposit.created", + "check_deposit.updated", + "check_transfer.created", + "check_transfer.updated", + "declined_transaction.created", + "digital_card_profile.created", + "digital_card_profile.updated", + "digital_wallet_token.created", + "digital_wallet_token.updated", + "document.created", + "entity.created", + "entity.updated", + "event_subscription.created", + "event_subscription.updated", + "export.created", + "export.updated", + "external_account.created", + "external_account.updated", + "fednow_transfer.created", + "fednow_transfer.updated", + "file.created", + "group.updated", + "group.heartbeat", + "inbound_ach_transfer.created", + "inbound_ach_transfer.updated", + "inbound_ach_transfer_return.created", + "inbound_ach_transfer_return.updated", + "inbound_check_deposit.created", + "inbound_check_deposit.updated", + "inbound_fednow_transfer.created", + "inbound_fednow_transfer.updated", + "inbound_mail_item.created", + "inbound_mail_item.updated", + "inbound_real_time_payments_transfer.created", + "inbound_real_time_payments_transfer.updated", + "inbound_wire_drawdown_request.created", + "inbound_wire_transfer.created", + "inbound_wire_transfer.updated", + "intrafi_account_enrollment.created", + "intrafi_account_enrollment.updated", + "intrafi_exclusion.created", + "intrafi_exclusion.updated", + "legacy_card_dispute.created", + "legacy_card_dispute.updated", + "lockbox.created", + "lockbox.updated", + "oauth_connection.created", + "oauth_connection.deactivated", + "card_push_transfer.created", + "card_push_transfer.updated", + "card_validation.created", + "card_validation.updated", + "pending_transaction.created", + "pending_transaction.updated", + "physical_card.created", + "physical_card.updated", + "physical_card_profile.created", + "physical_card_profile.updated", + "physical_check.created", + "physical_check.updated", + "program.created", + "program.updated", + "proof_of_authorization_request.created", + "proof_of_authorization_request.updated", + "real_time_decision.card_authorization_requested", + "real_time_decision.card_balance_inquiry_requested", + "real_time_decision.digital_wallet_token_requested", + "real_time_decision.digital_wallet_authentication_requested", + "real_time_decision.card_authentication_requested", + "real_time_decision.card_authentication_challenge_requested", + "real_time_payments_transfer.created", + "real_time_payments_transfer.updated", + "real_time_payments_request_for_payment.created", + "real_time_payments_request_for_payment.updated", + "swift_transfer.created", + "swift_transfer.updated", + "transaction.created", + "wire_drawdown_request.created", + "wire_drawdown_request.updated", + "wire_transfer.created", + "wire_transfer.updated", + ] + """The category of the Event. + + We may add additional possible values for this enum over time; your application + should be able to handle such additions gracefully. + + - `account.created` - Occurs whenever an Account is created. + - `account.updated` - Occurs whenever an Account is updated. + - `account_number.created` - Occurs whenever an Account Number is created. + - `account_number.updated` - Occurs whenever an Account Number is updated. + - `account_statement.created` - Occurs whenever an Account Statement is created. + - `account_transfer.created` - Occurs whenever an Account Transfer is created. + - `account_transfer.updated` - Occurs whenever an Account Transfer is updated. + - `ach_prenotification.created` - Occurs whenever an ACH Prenotification is + created. + - `ach_prenotification.updated` - Occurs whenever an ACH Prenotification is + updated. + - `ach_transfer.created` - Occurs whenever an ACH Transfer is created. + - `ach_transfer.updated` - Occurs whenever an ACH Transfer is updated. + - `blockchain_address.created` - Occurs whenever a Blockchain Address is + created. + - `blockchain_address.updated` - Occurs whenever a Blockchain Address is + updated. + - `blockchain_offramp_transfer.created` - Occurs whenever a Blockchain Off-Ramp + Transfer is created. + - `blockchain_offramp_transfer.updated` - Occurs whenever a Blockchain Off-Ramp + Transfer is updated. + - `blockchain_onramp_transfer.created` - Occurs whenever a Blockchain On-Ramp + Transfer is created. + - `blockchain_onramp_transfer.updated` - Occurs whenever a Blockchain On-Ramp + Transfer is updated. + - `bookkeeping_account.created` - Occurs whenever a Bookkeeping Account is + created. + - `bookkeeping_account.updated` - Occurs whenever a Bookkeeping Account is + updated. + - `bookkeeping_entry_set.updated` - Occurs whenever a Bookkeeping Entry Set is + created. + - `card.created` - Occurs whenever a Card is created. + - `card.updated` - Occurs whenever a Card is updated. + - `card_payment.created` - Occurs whenever a Card Payment is created. + - `card_payment.updated` - Occurs whenever a Card Payment is updated. + - `card_profile.created` - Occurs whenever a Card Profile is created. + - `card_profile.updated` - Occurs whenever a Card Profile is updated. + - `card_dispute.created` - Occurs whenever a Card Dispute is created. + - `card_dispute.updated` - Occurs whenever a Card Dispute is updated. + - `check_deposit.created` - Occurs whenever a Check Deposit is created. + - `check_deposit.updated` - Occurs whenever a Check Deposit is updated. + - `check_transfer.created` - Occurs whenever a Check Transfer is created. + - `check_transfer.updated` - Occurs whenever a Check Transfer is updated. + - `declined_transaction.created` - Occurs whenever a Declined Transaction is + created. + - `digital_card_profile.created` - Occurs whenever a Digital Card Profile is + created. + - `digital_card_profile.updated` - Occurs whenever a Digital Card Profile is + updated. + - `digital_wallet_token.created` - Occurs whenever a Digital Wallet Token is + created. + - `digital_wallet_token.updated` - Occurs whenever a Digital Wallet Token is + updated. + - `document.created` - Occurs whenever a Document is created. + - `entity.created` - Occurs whenever an Entity is created. + - `entity.updated` - Occurs whenever an Entity is updated. + - `event_subscription.created` - Occurs whenever an Event Subscription is + created. + - `event_subscription.updated` - Occurs whenever an Event Subscription is + updated. + - `export.created` - Occurs whenever an Export is created. + - `export.updated` - Occurs whenever an Export is updated. + - `external_account.created` - Occurs whenever an External Account is created. + - `external_account.updated` - Occurs whenever an External Account is updated. + - `fednow_transfer.created` - Occurs whenever a FedNow Transfer is created. + - `fednow_transfer.updated` - Occurs whenever a FedNow Transfer is updated. + - `file.created` - Occurs whenever a File is created. + - `group.updated` - Occurs whenever a Group is updated. + - `group.heartbeat` - Increase may send webhooks with this category to see if a + webhook endpoint is working properly. + - `inbound_ach_transfer.created` - Occurs whenever an Inbound ACH Transfer is + created. + - `inbound_ach_transfer.updated` - Occurs whenever an Inbound ACH Transfer is + updated. + - `inbound_ach_transfer_return.created` - Occurs whenever an Inbound ACH + Transfer Return is created. + - `inbound_ach_transfer_return.updated` - Occurs whenever an Inbound ACH + Transfer Return is updated. + - `inbound_check_deposit.created` - Occurs whenever an Inbound Check Deposit is + created. + - `inbound_check_deposit.updated` - Occurs whenever an Inbound Check Deposit is + updated. + - `inbound_fednow_transfer.created` - Occurs whenever an Inbound FedNow Transfer + is created. + - `inbound_fednow_transfer.updated` - Occurs whenever an Inbound FedNow Transfer + is updated. + - `inbound_mail_item.created` - Occurs whenever an Inbound Mail Item is created. + - `inbound_mail_item.updated` - Occurs whenever an Inbound Mail Item is updated. + - `inbound_real_time_payments_transfer.created` - Occurs whenever an Inbound + Real-Time Payments Transfer is created. + - `inbound_real_time_payments_transfer.updated` - Occurs whenever an Inbound + Real-Time Payments Transfer is updated. + - `inbound_wire_drawdown_request.created` - Occurs whenever an Inbound Wire + Drawdown Request is created. + - `inbound_wire_transfer.created` - Occurs whenever an Inbound Wire Transfer is + created. + - `inbound_wire_transfer.updated` - Occurs whenever an Inbound Wire Transfer is + updated. + - `intrafi_account_enrollment.created` - Occurs whenever an IntraFi Account + Enrollment is created. + - `intrafi_account_enrollment.updated` - Occurs whenever an IntraFi Account + Enrollment is updated. + - `intrafi_exclusion.created` - Occurs whenever an IntraFi Exclusion is created. + - `intrafi_exclusion.updated` - Occurs whenever an IntraFi Exclusion is updated. + - `legacy_card_dispute.created` - Occurs whenever a Legacy Card Dispute is + created. + - `legacy_card_dispute.updated` - Occurs whenever a Legacy Card Dispute is + updated. + - `lockbox.created` - Occurs whenever a Lockbox is created. + - `lockbox.updated` - Occurs whenever a Lockbox is updated. + - `oauth_connection.created` - Occurs whenever an OAuth Connection is created. + - `oauth_connection.deactivated` - Occurs whenever an OAuth Connection is + deactivated. + - `card_push_transfer.created` - Occurs whenever a Card Push Transfer is + created. + - `card_push_transfer.updated` - Occurs whenever a Card Push Transfer is + updated. + - `card_validation.created` - Occurs whenever a Card Validation is created. + - `card_validation.updated` - Occurs whenever a Card Validation is updated. + - `pending_transaction.created` - Occurs whenever a Pending Transaction is + created. + - `pending_transaction.updated` - Occurs whenever a Pending Transaction is + updated. + - `physical_card.created` - Occurs whenever a Physical Card is created. + - `physical_card.updated` - Occurs whenever a Physical Card is updated. + - `physical_card_profile.created` - Occurs whenever a Physical Card Profile is + created. + - `physical_card_profile.updated` - Occurs whenever a Physical Card Profile is + updated. + - `physical_check.created` - Occurs whenever a Physical Check is created. + - `physical_check.updated` - Occurs whenever a Physical Check is updated. + - `program.created` - Occurs whenever a Program is created. + - `program.updated` - Occurs whenever a Program is updated. + - `proof_of_authorization_request.created` - Occurs whenever a Proof of + Authorization Request is created. + - `proof_of_authorization_request.updated` - Occurs whenever a Proof of + Authorization Request is updated. + - `real_time_decision.card_authorization_requested` - Occurs whenever a + Real-Time Decision is created in response to a card authorization. + - `real_time_decision.card_balance_inquiry_requested` - Occurs whenever a + Real-Time Decision is created in response to a card balance inquiry. + - `real_time_decision.digital_wallet_token_requested` - Occurs whenever a + Real-Time Decision is created in response to a digital wallet provisioning + attempt. + - `real_time_decision.digital_wallet_authentication_requested` - Occurs whenever + a Real-Time Decision is created in response to a digital wallet requiring + two-factor authentication. + - `real_time_decision.card_authentication_requested` - Occurs whenever a + Real-Time Decision is created in response to 3DS authentication. + - `real_time_decision.card_authentication_challenge_requested` - Occurs whenever + a Real-Time Decision is created in response to 3DS authentication challenges. + - `real_time_payments_transfer.created` - Occurs whenever a Real-Time Payments + Transfer is created. + - `real_time_payments_transfer.updated` - Occurs whenever a Real-Time Payments + Transfer is updated. + - `real_time_payments_request_for_payment.created` - Occurs whenever a Real-Time + Payments Request for Payment is created. + - `real_time_payments_request_for_payment.updated` - Occurs whenever a Real-Time + Payments Request for Payment is updated. + - `swift_transfer.created` - Occurs whenever a Swift Transfer is created. + - `swift_transfer.updated` - Occurs whenever a Swift Transfer is updated. + - `transaction.created` - Occurs whenever a Transaction is created. + - `wire_drawdown_request.created` - Occurs whenever a Wire Drawdown Request is + created. + - `wire_drawdown_request.updated` - Occurs whenever a Wire Drawdown Request is + updated. + - `wire_transfer.created` - Occurs whenever a Wire Transfer is created. + - `wire_transfer.updated` - Occurs whenever a Wire Transfer is updated. + """ + + created_at: datetime + """The time the Event was created.""" + + type: Literal["event"] + """A constant representing the object's type. + + For this resource it will always be `event`. + """ diff --git a/src/increase/types/wire_drawdown_request_create_params.py b/src/increase/types/wire_drawdown_request_create_params.py index aca2bee42..7d9e8e37f 100644 --- a/src/increase/types/wire_drawdown_request_create_params.py +++ b/src/increase/types/wire_drawdown_request_create_params.py @@ -42,6 +42,12 @@ class WireDrawdownRequestCreateParams(TypedDict, total=False): debtor_routing_number: str """The debtor's routing number.""" + end_to_end_identification: str + """ + A free-form reference string set by the sender mirrored back in the subsequent + wire transfer. + """ + class CreditorAddress(TypedDict, total=False): """The creditor's address.""" diff --git a/src/increase/types/wire_transfer.py b/src/increase/types/wire_transfer.py index ec289f225..7f13befab 100644 --- a/src/increase/types/wire_transfer.py +++ b/src/increase/types/wire_transfer.py @@ -90,9 +90,6 @@ class CreatedByUser(BaseModel): class CreatedBy(BaseModel): """What object created the transfer, either via the API or the dashboard.""" - api_key: Optional[CreatedByAPIKey] = None - """If present, details about the API key that created the transfer.""" - category: Literal["api_key", "oauth_application", "user"] """The type of object that created this transfer. @@ -103,6 +100,9 @@ class CreatedBy(BaseModel): object. """ + api_key: Optional[CreatedByAPIKey] = None + """If present, details about the API key that created the transfer.""" + oauth_application: Optional[CreatedByOAuthApplication] = None """If present, details about the OAuth Application that created the transfer.""" diff --git a/src/increase/types/wire_transfer_list_params.py b/src/increase/types/wire_transfer_list_params.py index ae2166da1..ed7cfdca9 100644 --- a/src/increase/types/wire_transfer_list_params.py +++ b/src/increase/types/wire_transfer_list_params.py @@ -2,13 +2,13 @@ from __future__ import annotations -from typing import Union +from typing import List, Union from datetime import datetime -from typing_extensions import Annotated, TypedDict +from typing_extensions import Literal, Annotated, TypedDict from .._utils import PropertyInfo -__all__ = ["WireTransferListParams", "CreatedAt"] +__all__ = ["WireTransferListParams", "CreatedAt", "Status"] class WireTransferListParams(TypedDict, total=False): @@ -37,6 +37,8 @@ class WireTransferListParams(TypedDict, total=False): The default (and maximum) is 100 objects. """ + status: Status + class CreatedAt(TypedDict, total=False): after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] @@ -62,3 +64,28 @@ class CreatedAt(TypedDict, total=False): Return results on or before this [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) timestamp. """ + + +_StatusReservedKeywords = TypedDict( + "_StatusReservedKeywords", + { + "in": List[ + Literal[ + "pending_approval", + "canceled", + "pending_reviewing", + "rejected", + "requires_attention", + "pending_creating", + "reversed", + "submitted", + "complete", + ] + ], + }, + total=False, +) + + +class Status(_StatusReservedKeywords, total=False): + pass diff --git a/tests/api_resources/simulations/test_card_authentications.py b/tests/api_resources/simulations/test_card_authentications.py new file mode 100644 index 000000000..6f5aabc2b --- /dev/null +++ b/tests/api_resources/simulations/test_card_authentications.py @@ -0,0 +1,274 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from increase import Increase, AsyncIncrease +from tests.utils import assert_matches_type +from increase.types import CardPayment + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCardAuthentications: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Increase) -> None: + card_authentication = client.simulations.card_authentications.create( + card_id="card_oubs0hwk5rn6knuecxg2", + ) + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Increase) -> None: + card_authentication = client.simulations.card_authentications.create( + card_id="card_oubs0hwk5rn6knuecxg2", + category="payment_authentication", + device_channel="app", + merchant_acceptor_id="5665270011000168", + merchant_category_code="5734", + merchant_country="US", + merchant_name="x", + purchase_amount=1000, + ) + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Increase) -> None: + response = client.simulations.card_authentications.with_raw_response.create( + card_id="card_oubs0hwk5rn6knuecxg2", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_authentication = response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Increase) -> None: + with client.simulations.card_authentications.with_streaming_response.create( + card_id="card_oubs0hwk5rn6knuecxg2", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card_authentication = response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_challenge_attempts(self, client: Increase) -> None: + card_authentication = client.simulations.card_authentications.challenge_attempts( + card_payment_id="card_payment_nd3k2kacrqjli8482ave", + one_time_code="123456", + ) + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + def test_raw_response_challenge_attempts(self, client: Increase) -> None: + response = client.simulations.card_authentications.with_raw_response.challenge_attempts( + card_payment_id="card_payment_nd3k2kacrqjli8482ave", + one_time_code="123456", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_authentication = response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + def test_streaming_response_challenge_attempts(self, client: Increase) -> None: + with client.simulations.card_authentications.with_streaming_response.challenge_attempts( + card_payment_id="card_payment_nd3k2kacrqjli8482ave", + one_time_code="123456", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card_authentication = response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_challenge_attempts(self, client: Increase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_payment_id` but received ''"): + client.simulations.card_authentications.with_raw_response.challenge_attempts( + card_payment_id="", + one_time_code="123456", + ) + + @parametrize + def test_method_challenges(self, client: Increase) -> None: + card_authentication = client.simulations.card_authentications.challenges( + "card_payment_nd3k2kacrqjli8482ave", + ) + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + def test_raw_response_challenges(self, client: Increase) -> None: + response = client.simulations.card_authentications.with_raw_response.challenges( + "card_payment_nd3k2kacrqjli8482ave", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_authentication = response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + def test_streaming_response_challenges(self, client: Increase) -> None: + with client.simulations.card_authentications.with_streaming_response.challenges( + "card_payment_nd3k2kacrqjli8482ave", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card_authentication = response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_challenges(self, client: Increase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_payment_id` but received ''"): + client.simulations.card_authentications.with_raw_response.challenges( + "", + ) + + +class TestAsyncCardAuthentications: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncIncrease) -> None: + card_authentication = await async_client.simulations.card_authentications.create( + card_id="card_oubs0hwk5rn6knuecxg2", + ) + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncIncrease) -> None: + card_authentication = await async_client.simulations.card_authentications.create( + card_id="card_oubs0hwk5rn6knuecxg2", + category="payment_authentication", + device_channel="app", + merchant_acceptor_id="5665270011000168", + merchant_category_code="5734", + merchant_country="US", + merchant_name="x", + purchase_amount=1000, + ) + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncIncrease) -> None: + response = await async_client.simulations.card_authentications.with_raw_response.create( + card_id="card_oubs0hwk5rn6knuecxg2", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_authentication = await response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncIncrease) -> None: + async with async_client.simulations.card_authentications.with_streaming_response.create( + card_id="card_oubs0hwk5rn6knuecxg2", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card_authentication = await response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_challenge_attempts(self, async_client: AsyncIncrease) -> None: + card_authentication = await async_client.simulations.card_authentications.challenge_attempts( + card_payment_id="card_payment_nd3k2kacrqjli8482ave", + one_time_code="123456", + ) + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + async def test_raw_response_challenge_attempts(self, async_client: AsyncIncrease) -> None: + response = await async_client.simulations.card_authentications.with_raw_response.challenge_attempts( + card_payment_id="card_payment_nd3k2kacrqjli8482ave", + one_time_code="123456", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_authentication = await response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + async def test_streaming_response_challenge_attempts(self, async_client: AsyncIncrease) -> None: + async with async_client.simulations.card_authentications.with_streaming_response.challenge_attempts( + card_payment_id="card_payment_nd3k2kacrqjli8482ave", + one_time_code="123456", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card_authentication = await response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_challenge_attempts(self, async_client: AsyncIncrease) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_payment_id` but received ''"): + await async_client.simulations.card_authentications.with_raw_response.challenge_attempts( + card_payment_id="", + one_time_code="123456", + ) + + @parametrize + async def test_method_challenges(self, async_client: AsyncIncrease) -> None: + card_authentication = await async_client.simulations.card_authentications.challenges( + "card_payment_nd3k2kacrqjli8482ave", + ) + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + async def test_raw_response_challenges(self, async_client: AsyncIncrease) -> None: + response = await async_client.simulations.card_authentications.with_raw_response.challenges( + "card_payment_nd3k2kacrqjli8482ave", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + card_authentication = await response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + @parametrize + async def test_streaming_response_challenges(self, async_client: AsyncIncrease) -> None: + async with async_client.simulations.card_authentications.with_streaming_response.challenges( + "card_payment_nd3k2kacrqjli8482ave", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + card_authentication = await response.parse() + assert_matches_type(CardPayment, card_authentication, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_challenges(self, async_client: AsyncIncrease) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_payment_id` but received ''"): + await async_client.simulations.card_authentications.with_raw_response.challenges( + "", + ) diff --git a/tests/api_resources/simulations/test_check_deposits.py b/tests/api_resources/simulations/test_check_deposits.py index 3204a3796..9d422a43a 100644 --- a/tests/api_resources/simulations/test_check_deposits.py +++ b/tests/api_resources/simulations/test_check_deposits.py @@ -17,6 +17,53 @@ class TestCheckDeposits: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + @parametrize + def test_method_adjustment(self, client: Increase) -> None: + check_deposit = client.simulations.check_deposits.adjustment( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + ) + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + @parametrize + def test_method_adjustment_with_all_params(self, client: Increase) -> None: + check_deposit = client.simulations.check_deposits.adjustment( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + amount=-1000000000, + reason="late_return", + ) + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + @parametrize + def test_raw_response_adjustment(self, client: Increase) -> None: + response = client.simulations.check_deposits.with_raw_response.adjustment( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + check_deposit = response.parse() + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + @parametrize + def test_streaming_response_adjustment(self, client: Increase) -> None: + with client.simulations.check_deposits.with_streaming_response.adjustment( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + check_deposit = response.parse() + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_adjustment(self, client: Increase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `check_deposit_id` but received ''"): + client.simulations.check_deposits.with_raw_response.adjustment( + check_deposit_id="", + ) + @parametrize def test_method_reject(self, client: Increase) -> None: check_deposit = client.simulations.check_deposits.reject( @@ -96,14 +143,26 @@ def test_path_params_return(self, client: Increase) -> None: @parametrize def test_method_submit(self, client: Increase) -> None: check_deposit = client.simulations.check_deposits.submit( - "check_deposit_f06n9gpg7sxn8t19lfc1", + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + ) + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + @parametrize + def test_method_submit_with_all_params(self, client: Increase) -> None: + check_deposit = client.simulations.check_deposits.submit( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + scan={ + "account_number": "x", + "routing_number": "x", + "auxiliary_on_us": "x", + }, ) assert_matches_type(CheckDeposit, check_deposit, path=["response"]) @parametrize def test_raw_response_submit(self, client: Increase) -> None: response = client.simulations.check_deposits.with_raw_response.submit( - "check_deposit_f06n9gpg7sxn8t19lfc1", + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", ) assert response.is_closed is True @@ -114,7 +173,7 @@ def test_raw_response_submit(self, client: Increase) -> None: @parametrize def test_streaming_response_submit(self, client: Increase) -> None: with client.simulations.check_deposits.with_streaming_response.submit( - "check_deposit_f06n9gpg7sxn8t19lfc1", + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -128,7 +187,7 @@ def test_streaming_response_submit(self, client: Increase) -> None: def test_path_params_submit(self, client: Increase) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `check_deposit_id` but received ''"): client.simulations.check_deposits.with_raw_response.submit( - "", + check_deposit_id="", ) @@ -137,6 +196,53 @@ class TestAsyncCheckDeposits: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) + @parametrize + async def test_method_adjustment(self, async_client: AsyncIncrease) -> None: + check_deposit = await async_client.simulations.check_deposits.adjustment( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + ) + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + @parametrize + async def test_method_adjustment_with_all_params(self, async_client: AsyncIncrease) -> None: + check_deposit = await async_client.simulations.check_deposits.adjustment( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + amount=-1000000000, + reason="late_return", + ) + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + @parametrize + async def test_raw_response_adjustment(self, async_client: AsyncIncrease) -> None: + response = await async_client.simulations.check_deposits.with_raw_response.adjustment( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + check_deposit = await response.parse() + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + @parametrize + async def test_streaming_response_adjustment(self, async_client: AsyncIncrease) -> None: + async with async_client.simulations.check_deposits.with_streaming_response.adjustment( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + check_deposit = await response.parse() + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_adjustment(self, async_client: AsyncIncrease) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `check_deposit_id` but received ''"): + await async_client.simulations.check_deposits.with_raw_response.adjustment( + check_deposit_id="", + ) + @parametrize async def test_method_reject(self, async_client: AsyncIncrease) -> None: check_deposit = await async_client.simulations.check_deposits.reject( @@ -216,14 +322,26 @@ async def test_path_params_return(self, async_client: AsyncIncrease) -> None: @parametrize async def test_method_submit(self, async_client: AsyncIncrease) -> None: check_deposit = await async_client.simulations.check_deposits.submit( - "check_deposit_f06n9gpg7sxn8t19lfc1", + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + ) + assert_matches_type(CheckDeposit, check_deposit, path=["response"]) + + @parametrize + async def test_method_submit_with_all_params(self, async_client: AsyncIncrease) -> None: + check_deposit = await async_client.simulations.check_deposits.submit( + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", + scan={ + "account_number": "x", + "routing_number": "x", + "auxiliary_on_us": "x", + }, ) assert_matches_type(CheckDeposit, check_deposit, path=["response"]) @parametrize async def test_raw_response_submit(self, async_client: AsyncIncrease) -> None: response = await async_client.simulations.check_deposits.with_raw_response.submit( - "check_deposit_f06n9gpg7sxn8t19lfc1", + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", ) assert response.is_closed is True @@ -234,7 +352,7 @@ async def test_raw_response_submit(self, async_client: AsyncIncrease) -> None: @parametrize async def test_streaming_response_submit(self, async_client: AsyncIncrease) -> None: async with async_client.simulations.check_deposits.with_streaming_response.submit( - "check_deposit_f06n9gpg7sxn8t19lfc1", + check_deposit_id="check_deposit_f06n9gpg7sxn8t19lfc1", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -248,5 +366,5 @@ async def test_streaming_response_submit(self, async_client: AsyncIncrease) -> N async def test_path_params_submit(self, async_client: AsyncIncrease) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `check_deposit_id` but received ''"): await async_client.simulations.check_deposits.with_raw_response.submit( - "", + check_deposit_id="", ) diff --git a/tests/api_resources/simulations/test_inbound_check_deposits.py b/tests/api_resources/simulations/test_inbound_check_deposits.py index eef5ded60..44a6f16a6 100644 --- a/tests/api_resources/simulations/test_inbound_check_deposits.py +++ b/tests/api_resources/simulations/test_inbound_check_deposits.py @@ -64,6 +64,55 @@ def test_streaming_response_create(self, client: Increase) -> None: assert cast(Any, response.is_closed) is True + @parametrize + def test_method_adjustment(self, client: Increase) -> None: + inbound_check_deposit = client.simulations.inbound_check_deposits.adjustment( + inbound_check_deposit_id="inbound_check_deposit_zoshvqybq0cjjm31mra", + ) + assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) + + @parametrize + def test_method_adjustment_with_all_params(self, client: Increase) -> None: + inbound_check_deposit = client.simulations.inbound_check_deposits.adjustment( + inbound_check_deposit_id="inbound_check_deposit_zoshvqybq0cjjm31mra", + amount=1000, + reason="late_return", + ) + assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) + + @parametrize + def test_raw_response_adjustment(self, client: Increase) -> None: + response = client.simulations.inbound_check_deposits.with_raw_response.adjustment( + inbound_check_deposit_id="inbound_check_deposit_zoshvqybq0cjjm31mra", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + inbound_check_deposit = response.parse() + assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) + + @parametrize + def test_streaming_response_adjustment(self, client: Increase) -> None: + with client.simulations.inbound_check_deposits.with_streaming_response.adjustment( + inbound_check_deposit_id="inbound_check_deposit_zoshvqybq0cjjm31mra", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + inbound_check_deposit = response.parse() + assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_adjustment(self, client: Increase) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `inbound_check_deposit_id` but received ''" + ): + client.simulations.inbound_check_deposits.with_raw_response.adjustment( + inbound_check_deposit_id="", + ) + class TestAsyncInboundCheckDeposits: parametrize = pytest.mark.parametrize( @@ -116,3 +165,52 @@ async def test_streaming_response_create(self, async_client: AsyncIncrease) -> N assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_adjustment(self, async_client: AsyncIncrease) -> None: + inbound_check_deposit = await async_client.simulations.inbound_check_deposits.adjustment( + inbound_check_deposit_id="inbound_check_deposit_zoshvqybq0cjjm31mra", + ) + assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) + + @parametrize + async def test_method_adjustment_with_all_params(self, async_client: AsyncIncrease) -> None: + inbound_check_deposit = await async_client.simulations.inbound_check_deposits.adjustment( + inbound_check_deposit_id="inbound_check_deposit_zoshvqybq0cjjm31mra", + amount=1000, + reason="late_return", + ) + assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) + + @parametrize + async def test_raw_response_adjustment(self, async_client: AsyncIncrease) -> None: + response = await async_client.simulations.inbound_check_deposits.with_raw_response.adjustment( + inbound_check_deposit_id="inbound_check_deposit_zoshvqybq0cjjm31mra", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + inbound_check_deposit = await response.parse() + assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) + + @parametrize + async def test_streaming_response_adjustment(self, async_client: AsyncIncrease) -> None: + async with async_client.simulations.inbound_check_deposits.with_streaming_response.adjustment( + inbound_check_deposit_id="inbound_check_deposit_zoshvqybq0cjjm31mra", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + inbound_check_deposit = await response.parse() + assert_matches_type(InboundCheckDeposit, inbound_check_deposit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_adjustment(self, async_client: AsyncIncrease) -> None: + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `inbound_check_deposit_id` but received ''" + ): + await async_client.simulations.inbound_check_deposits.with_raw_response.adjustment( + inbound_check_deposit_id="", + ) diff --git a/tests/api_resources/simulations/test_programs.py b/tests/api_resources/simulations/test_programs.py index 1439c6bcf..72c010c9e 100644 --- a/tests/api_resources/simulations/test_programs.py +++ b/tests/api_resources/simulations/test_programs.py @@ -28,7 +28,8 @@ def test_method_create(self, client: Increase) -> None: def test_method_create_with_all_params(self, client: Increase) -> None: program = client.simulations.programs.create( name="For Benefit Of", - bank="blue_ridge_bank", + bank="core_bank", + lending_maximum_extendable_credit=0, reserve_account_id="reserve_account_id", ) assert_matches_type(Program, program, path=["response"]) @@ -74,7 +75,8 @@ async def test_method_create(self, async_client: AsyncIncrease) -> None: async def test_method_create_with_all_params(self, async_client: AsyncIncrease) -> None: program = await async_client.simulations.programs.create( name="For Benefit Of", - bank="blue_ridge_bank", + bank="core_bank", + lending_maximum_extendable_credit=0, reserve_account_id="reserve_account_id", ) assert_matches_type(Program, program, path=["response"]) diff --git a/tests/api_resources/test_accounts.py b/tests/api_resources/test_accounts.py index d6edc5ab9..d208450c5 100644 --- a/tests/api_resources/test_accounts.py +++ b/tests/api_resources/test_accounts.py @@ -13,7 +13,7 @@ Account, BalanceLookup, ) -from increase._utils import parse_datetime +from increase._utils import parse_date, parse_datetime from increase.pagination import SyncPage, AsyncPage base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -34,7 +34,15 @@ def test_method_create_with_all_params(self, client: Increase) -> None: account = client.accounts.create( name="New Account!", entity_id="entity_n8y8tnk2p9339ti393yi", + funding="loan", informational_entity_id="informational_entity_id", + loan={ + "credit_limit": 0, + "grace_period_days": 0, + "statement_day_of_month": 1, + "statement_payment_type": "balance", + "maturity_date": parse_date("2019-12-27"), + }, program_id="program_i2v2os4mwza1oetokh9i", ) assert_matches_type(Account, account, path=["response"]) @@ -112,7 +120,7 @@ def test_method_update(self, client: Increase) -> None: def test_method_update_with_all_params(self, client: Increase) -> None: account = client.accounts.update( account_id="account_in71c4amph0vgo2qllky", - credit_limit=0, + loan={"credit_limit": 0}, name="My renamed account", ) assert_matches_type(Account, account, path=["response"]) @@ -294,7 +302,15 @@ async def test_method_create_with_all_params(self, async_client: AsyncIncrease) account = await async_client.accounts.create( name="New Account!", entity_id="entity_n8y8tnk2p9339ti393yi", + funding="loan", informational_entity_id="informational_entity_id", + loan={ + "credit_limit": 0, + "grace_period_days": 0, + "statement_day_of_month": 1, + "statement_payment_type": "balance", + "maturity_date": parse_date("2019-12-27"), + }, program_id="program_i2v2os4mwza1oetokh9i", ) assert_matches_type(Account, account, path=["response"]) @@ -372,7 +388,7 @@ async def test_method_update(self, async_client: AsyncIncrease) -> None: async def test_method_update_with_all_params(self, async_client: AsyncIncrease) -> None: account = await async_client.accounts.update( account_id="account_in71c4amph0vgo2qllky", - credit_limit=0, + loan={"credit_limit": 0}, name="My renamed account", ) assert_matches_type(Account, account, path=["response"]) diff --git a/tests/api_resources/test_card_disputes.py b/tests/api_resources/test_card_disputes.py index 0ce895086..8557c6742 100644 --- a/tests/api_resources/test_card_disputes.py +++ b/tests/api_resources/test_card_disputes.py @@ -698,14 +698,22 @@ def test_path_params_submit_user_submission(self, client: Increase) -> None: @parametrize def test_method_withdraw(self, client: Increase) -> None: card_dispute = client.card_disputes.withdraw( - "card_dispute_h9sc95nbl1cgltpp7men", + card_dispute_id="card_dispute_h9sc95nbl1cgltpp7men", + ) + assert_matches_type(CardDispute, card_dispute, path=["response"]) + + @parametrize + def test_method_withdraw_with_all_params(self, client: Increase) -> None: + card_dispute = client.card_disputes.withdraw( + card_dispute_id="card_dispute_h9sc95nbl1cgltpp7men", + explanation="The explanation for withdrawing the Card Dispute.", ) assert_matches_type(CardDispute, card_dispute, path=["response"]) @parametrize def test_raw_response_withdraw(self, client: Increase) -> None: response = client.card_disputes.with_raw_response.withdraw( - "card_dispute_h9sc95nbl1cgltpp7men", + card_dispute_id="card_dispute_h9sc95nbl1cgltpp7men", ) assert response.is_closed is True @@ -716,7 +724,7 @@ def test_raw_response_withdraw(self, client: Increase) -> None: @parametrize def test_streaming_response_withdraw(self, client: Increase) -> None: with client.card_disputes.with_streaming_response.withdraw( - "card_dispute_h9sc95nbl1cgltpp7men", + card_dispute_id="card_dispute_h9sc95nbl1cgltpp7men", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -730,7 +738,7 @@ def test_streaming_response_withdraw(self, client: Increase) -> None: def test_path_params_withdraw(self, client: Increase) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_dispute_id` but received ''"): client.card_disputes.with_raw_response.withdraw( - "", + card_dispute_id="", ) @@ -1416,14 +1424,22 @@ async def test_path_params_submit_user_submission(self, async_client: AsyncIncre @parametrize async def test_method_withdraw(self, async_client: AsyncIncrease) -> None: card_dispute = await async_client.card_disputes.withdraw( - "card_dispute_h9sc95nbl1cgltpp7men", + card_dispute_id="card_dispute_h9sc95nbl1cgltpp7men", + ) + assert_matches_type(CardDispute, card_dispute, path=["response"]) + + @parametrize + async def test_method_withdraw_with_all_params(self, async_client: AsyncIncrease) -> None: + card_dispute = await async_client.card_disputes.withdraw( + card_dispute_id="card_dispute_h9sc95nbl1cgltpp7men", + explanation="The explanation for withdrawing the Card Dispute.", ) assert_matches_type(CardDispute, card_dispute, path=["response"]) @parametrize async def test_raw_response_withdraw(self, async_client: AsyncIncrease) -> None: response = await async_client.card_disputes.with_raw_response.withdraw( - "card_dispute_h9sc95nbl1cgltpp7men", + card_dispute_id="card_dispute_h9sc95nbl1cgltpp7men", ) assert response.is_closed is True @@ -1434,7 +1450,7 @@ async def test_raw_response_withdraw(self, async_client: AsyncIncrease) -> None: @parametrize async def test_streaming_response_withdraw(self, async_client: AsyncIncrease) -> None: async with async_client.card_disputes.with_streaming_response.withdraw( - "card_dispute_h9sc95nbl1cgltpp7men", + card_dispute_id="card_dispute_h9sc95nbl1cgltpp7men", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1448,5 +1464,5 @@ async def test_streaming_response_withdraw(self, async_client: AsyncIncrease) -> async def test_path_params_withdraw(self, async_client: AsyncIncrease) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `card_dispute_id` but received ''"): await async_client.card_disputes.with_raw_response.withdraw( - "", + card_dispute_id="", ) diff --git a/tests/api_resources/test_entities.py b/tests/api_resources/test_entities.py index f51067d0a..96e4f3ea4 100644 --- a/tests/api_resources/test_entities.py +++ b/tests/api_resources/test_entities.py @@ -367,6 +367,7 @@ def test_method_update_with_all_params(self, client: Increase) -> None: "incorporation_state": "x", "industry_code": "x", "name": "x", + "tax_identifier": "x", }, details_confirmed_at=parse_datetime("2019-12-27T18:11:19.117Z"), government_authority={ @@ -562,52 +563,6 @@ def test_path_params_archive_beneficial_owner(self, client: Increase) -> None: beneficial_owner_id="entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", ) - @parametrize - def test_method_confirm(self, client: Increase) -> None: - entity = client.entities.confirm( - entity_id="entity_n8y8tnk2p9339ti393yi", - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - def test_method_confirm_with_all_params(self, client: Increase) -> None: - entity = client.entities.confirm( - entity_id="entity_n8y8tnk2p9339ti393yi", - confirmed_at=parse_datetime("2019-12-27T18:11:19.117Z"), - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - def test_raw_response_confirm(self, client: Increase) -> None: - response = client.entities.with_raw_response.confirm( - entity_id="entity_n8y8tnk2p9339ti393yi", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entity = response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - def test_streaming_response_confirm(self, client: Increase) -> None: - with client.entities.with_streaming_response.confirm( - entity_id="entity_n8y8tnk2p9339ti393yi", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entity = response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_confirm(self, client: Increase) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entity_id` but received ''"): - client.entities.with_raw_response.confirm( - entity_id="", - ) - @parametrize def test_method_create_beneficial_owner(self, client: Increase) -> None: entity = client.entities.create_beneficial_owner( @@ -756,82 +711,6 @@ def test_path_params_create_beneficial_owner(self, client: Increase) -> None: }, ) - @parametrize - def test_method_update_address(self, client: Increase) -> None: - entity = client.entities.update_address( - entity_id="entity_n8y8tnk2p9339ti393yi", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - }, - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - def test_method_update_address_with_all_params(self, client: Increase) -> None: - entity = client.entities.update_address( - entity_id="entity_n8y8tnk2p9339ti393yi", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - "line2": "Unit 2", - }, - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - def test_raw_response_update_address(self, client: Increase) -> None: - response = client.entities.with_raw_response.update_address( - entity_id="entity_n8y8tnk2p9339ti393yi", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - }, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entity = response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - def test_streaming_response_update_address(self, client: Increase) -> None: - with client.entities.with_streaming_response.update_address( - entity_id="entity_n8y8tnk2p9339ti393yi", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - }, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entity = response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_update_address(self, client: Increase) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entity_id` but received ''"): - client.entities.with_raw_response.update_address( - entity_id="", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - }, - ) - @parametrize def test_method_update_beneficial_owner_address(self, client: Increase) -> None: entity = client.entities.update_beneficial_owner_address( @@ -910,48 +789,6 @@ def test_path_params_update_beneficial_owner_address(self, client: Increase) -> beneficial_owner_id="entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", ) - @parametrize - def test_method_update_industry_code(self, client: Increase) -> None: - entity = client.entities.update_industry_code( - entity_id="entity_n8y8tnk2p9339ti393yi", - industry_code="5132", - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - def test_raw_response_update_industry_code(self, client: Increase) -> None: - response = client.entities.with_raw_response.update_industry_code( - entity_id="entity_n8y8tnk2p9339ti393yi", - industry_code="5132", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entity = response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - def test_streaming_response_update_industry_code(self, client: Increase) -> None: - with client.entities.with_streaming_response.update_industry_code( - entity_id="entity_n8y8tnk2p9339ti393yi", - industry_code="5132", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entity = response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_update_industry_code(self, client: Increase) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entity_id` but received ''"): - client.entities.with_raw_response.update_industry_code( - entity_id="", - industry_code="5132", - ) - class TestAsyncEntities: parametrize = pytest.mark.parametrize( @@ -1304,6 +1141,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncIncrease) "incorporation_state": "x", "industry_code": "x", "name": "x", + "tax_identifier": "x", }, details_confirmed_at=parse_datetime("2019-12-27T18:11:19.117Z"), government_authority={ @@ -1499,52 +1337,6 @@ async def test_path_params_archive_beneficial_owner(self, async_client: AsyncInc beneficial_owner_id="entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", ) - @parametrize - async def test_method_confirm(self, async_client: AsyncIncrease) -> None: - entity = await async_client.entities.confirm( - entity_id="entity_n8y8tnk2p9339ti393yi", - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - async def test_method_confirm_with_all_params(self, async_client: AsyncIncrease) -> None: - entity = await async_client.entities.confirm( - entity_id="entity_n8y8tnk2p9339ti393yi", - confirmed_at=parse_datetime("2019-12-27T18:11:19.117Z"), - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - async def test_raw_response_confirm(self, async_client: AsyncIncrease) -> None: - response = await async_client.entities.with_raw_response.confirm( - entity_id="entity_n8y8tnk2p9339ti393yi", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entity = await response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - async def test_streaming_response_confirm(self, async_client: AsyncIncrease) -> None: - async with async_client.entities.with_streaming_response.confirm( - entity_id="entity_n8y8tnk2p9339ti393yi", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entity = await response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_confirm(self, async_client: AsyncIncrease) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entity_id` but received ''"): - await async_client.entities.with_raw_response.confirm( - entity_id="", - ) - @parametrize async def test_method_create_beneficial_owner(self, async_client: AsyncIncrease) -> None: entity = await async_client.entities.create_beneficial_owner( @@ -1693,82 +1485,6 @@ async def test_path_params_create_beneficial_owner(self, async_client: AsyncIncr }, ) - @parametrize - async def test_method_update_address(self, async_client: AsyncIncrease) -> None: - entity = await async_client.entities.update_address( - entity_id="entity_n8y8tnk2p9339ti393yi", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - }, - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - async def test_method_update_address_with_all_params(self, async_client: AsyncIncrease) -> None: - entity = await async_client.entities.update_address( - entity_id="entity_n8y8tnk2p9339ti393yi", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - "line2": "Unit 2", - }, - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - async def test_raw_response_update_address(self, async_client: AsyncIncrease) -> None: - response = await async_client.entities.with_raw_response.update_address( - entity_id="entity_n8y8tnk2p9339ti393yi", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - }, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entity = await response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - async def test_streaming_response_update_address(self, async_client: AsyncIncrease) -> None: - async with async_client.entities.with_streaming_response.update_address( - entity_id="entity_n8y8tnk2p9339ti393yi", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - }, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entity = await response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_update_address(self, async_client: AsyncIncrease) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entity_id` but received ''"): - await async_client.entities.with_raw_response.update_address( - entity_id="", - address={ - "city": "New York", - "line1": "33 Liberty Street", - "state": "NY", - "zip": "10045", - }, - ) - @parametrize async def test_method_update_beneficial_owner_address(self, async_client: AsyncIncrease) -> None: entity = await async_client.entities.update_beneficial_owner_address( @@ -1846,45 +1562,3 @@ async def test_path_params_update_beneficial_owner_address(self, async_client: A }, beneficial_owner_id="entity_setup_beneficial_owner_submission_vgkyk7dj5eb4sfhdbkx7", ) - - @parametrize - async def test_method_update_industry_code(self, async_client: AsyncIncrease) -> None: - entity = await async_client.entities.update_industry_code( - entity_id="entity_n8y8tnk2p9339ti393yi", - industry_code="5132", - ) - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - async def test_raw_response_update_industry_code(self, async_client: AsyncIncrease) -> None: - response = await async_client.entities.with_raw_response.update_industry_code( - entity_id="entity_n8y8tnk2p9339ti393yi", - industry_code="5132", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entity = await response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - @parametrize - async def test_streaming_response_update_industry_code(self, async_client: AsyncIncrease) -> None: - async with async_client.entities.with_streaming_response.update_industry_code( - entity_id="entity_n8y8tnk2p9339ti393yi", - industry_code="5132", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entity = await response.parse() - assert_matches_type(Entity, entity, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_update_industry_code(self, async_client: AsyncIncrease) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entity_id` but received ''"): - await async_client.entities.with_raw_response.update_industry_code( - entity_id="", - industry_code="5132", - ) diff --git a/tests/api_resources/test_event_subscriptions.py b/tests/api_resources/test_event_subscriptions.py index f8577e2cf..2962c9c00 100644 --- a/tests/api_resources/test_event_subscriptions.py +++ b/tests/api_resources/test_event_subscriptions.py @@ -32,7 +32,7 @@ def test_method_create_with_all_params(self, client: Increase) -> None: event_subscription = client.event_subscriptions.create( url="https://website.com/webhooks", oauth_connection_id="x", - selected_event_category="account.created", + selected_event_categories=[{"event_category": "account.created"}], shared_secret="x", status="active", ) @@ -198,7 +198,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncIncrease) event_subscription = await async_client.event_subscriptions.create( url="https://website.com/webhooks", oauth_connection_id="x", - selected_event_category="account.created", + selected_event_categories=[{"event_category": "account.created"}], shared_secret="x", status="active", ) diff --git a/tests/api_resources/test_events.py b/tests/api_resources/test_events.py index 101cba4be..55aacb27c 100644 --- a/tests/api_resources/test_events.py +++ b/tests/api_resources/test_events.py @@ -4,8 +4,10 @@ import os from typing import Any, cast +from datetime import datetime, timezone import pytest +import standardwebhooks from increase import Increase, AsyncIncrease from tests.utils import assert_matches_type @@ -98,6 +100,45 @@ def test_streaming_response_list(self, client: Increase) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.parametrize( + "client_opt,method_opt", + [ + ("secret\n", None), + ("wrong", b"secret\n"), + ("wrong", "whsec_c2VjcmV0Cg=="), + (None, b"secret\n"), + (None, "whsec_c2VjcmV0Cg=="), + ], + ) + def test_method_unwrap(self, client: Increase, client_opt: str | None, method_opt: str | bytes | None) -> None: + hook = standardwebhooks.Webhook(b"secret\n") + + client = client.with_options(webhook_secret=client_opt) + + data = """{"id":"event_001dzz0r20rzr4zrhrr1364hy80","associated_object_id":"account_in71c4amph0vgo2qllky","associated_object_type":"account","category":"account.created","created_at":"2020-01-31T23:59:59Z","type":"event"}""" + msg_id = "1" + timestamp = datetime.now(tz=timezone.utc) + sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) + headers = { + "webhook-id": msg_id, + "webhook-timestamp": str(int(timestamp.timestamp())), + "webhook-signature": sig, + } + + try: + _ = client.events.unwrap(data, headers=headers, key=method_opt) + except standardwebhooks.WebhookVerificationError as e: + raise AssertionError("Failed to unwrap valid webhook") from e + + bad_headers = [ + {**headers, "webhook-signature": hook.sign(msg_id=msg_id, timestamp=timestamp, data="xxx")}, + {**headers, "webhook-id": "bad"}, + {**headers, "webhook-timestamp": "0"}, + ] + for bad_header in bad_headers: + with pytest.raises(standardwebhooks.WebhookVerificationError): + _ = client.events.unwrap(data, headers=bad_header, key=method_opt) + class TestAsyncEvents: parametrize = pytest.mark.parametrize( @@ -182,3 +223,44 @@ async def test_streaming_response_list(self, async_client: AsyncIncrease) -> Non assert_matches_type(AsyncPage[Event], event, path=["response"]) assert cast(Any, response.is_closed) is True + + @pytest.mark.parametrize( + "client_opt,method_opt", + [ + ("secret\n", None), + ("wrong", b"secret\n"), + ("wrong", "whsec_c2VjcmV0Cg=="), + (None, b"secret\n"), + (None, "whsec_c2VjcmV0Cg=="), + ], + ) + def test_method_unwrap( + self, async_client: Increase, client_opt: str | None, method_opt: str | bytes | None + ) -> None: + hook = standardwebhooks.Webhook(b"secret\n") + + async_client = async_client.with_options(webhook_secret=client_opt) + + data = """{"id":"event_001dzz0r20rzr4zrhrr1364hy80","associated_object_id":"account_in71c4amph0vgo2qllky","associated_object_type":"account","category":"account.created","created_at":"2020-01-31T23:59:59Z","type":"event"}""" + msg_id = "1" + timestamp = datetime.now(tz=timezone.utc) + sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data) + headers = { + "webhook-id": msg_id, + "webhook-timestamp": str(int(timestamp.timestamp())), + "webhook-signature": sig, + } + + try: + _ = async_client.events.unwrap(data, headers=headers, key=method_opt) + except standardwebhooks.WebhookVerificationError as e: + raise AssertionError("Failed to unwrap valid webhook") from e + + bad_headers = [ + {**headers, "webhook-signature": hook.sign(msg_id=msg_id, timestamp=timestamp, data="xxx")}, + {**headers, "webhook-id": "bad"}, + {**headers, "webhook-timestamp": "0"}, + ] + for bad_header in bad_headers: + with pytest.raises(standardwebhooks.WebhookVerificationError): + _ = async_client.events.unwrap(data, headers=bad_header, key=method_opt) diff --git a/tests/api_resources/test_exports.py b/tests/api_resources/test_exports.py index 9ecc5044c..8325f22de 100644 --- a/tests/api_resources/test_exports.py +++ b/tests/api_resources/test_exports.py @@ -56,7 +56,6 @@ def test_method_create_with_all_params(self, client: Increase) -> None: "on_or_after": parse_datetime("2019-12-27T18:11:19.117Z"), "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), }, - "program_id": "program_id", }, bookkeeping_account_balance_csv={ "bookkeeping_account_id": "bookkeeping_account_id", @@ -67,7 +66,7 @@ def test_method_create_with_all_params(self, client: Increase) -> None: "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), }, }, - entity_csv={"status": {"in": ["active"]}}, + entity_csv={}, funding_instructions={"account_number_id": "account_number_id"}, transaction_csv={ "account_id": "account_in71c4amph0vgo2qllky", @@ -77,9 +76,12 @@ def test_method_create_with_all_params(self, client: Increase) -> None: "on_or_after": parse_datetime("2019-12-27T18:11:19.117Z"), "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), }, - "program_id": "program_id", }, vendor_csv={}, + voided_check={ + "account_number_id": "account_number_id", + "payer": [{"line": "x"}], + }, ) assert_matches_type(Export, export, path=["response"]) @@ -153,7 +155,7 @@ def test_method_list(self, client: Increase) -> None: @parametrize def test_method_list_with_all_params(self, client: Increase) -> None: export = client.exports.list( - category={"in": ["account_statement_ofx"]}, + category="account_statement_ofx", created_at={ "after": parse_datetime("2019-12-27T18:11:19.117Z"), "before": parse_datetime("2019-12-27T18:11:19.117Z"), @@ -161,6 +163,8 @@ def test_method_list_with_all_params(self, client: Increase) -> None: "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), }, cursor="cursor", + form_1099_int={"account_id": "account_id"}, + form_1099_misc={"account_id": "account_id"}, idempotency_key="x", limit=1, status={"in": ["pending"]}, @@ -230,7 +234,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncIncrease) "on_or_after": parse_datetime("2019-12-27T18:11:19.117Z"), "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), }, - "program_id": "program_id", }, bookkeeping_account_balance_csv={ "bookkeeping_account_id": "bookkeeping_account_id", @@ -241,7 +244,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncIncrease) "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), }, }, - entity_csv={"status": {"in": ["active"]}}, + entity_csv={}, funding_instructions={"account_number_id": "account_number_id"}, transaction_csv={ "account_id": "account_in71c4amph0vgo2qllky", @@ -251,9 +254,12 @@ async def test_method_create_with_all_params(self, async_client: AsyncIncrease) "on_or_after": parse_datetime("2019-12-27T18:11:19.117Z"), "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), }, - "program_id": "program_id", }, vendor_csv={}, + voided_check={ + "account_number_id": "account_number_id", + "payer": [{"line": "x"}], + }, ) assert_matches_type(Export, export, path=["response"]) @@ -327,7 +333,7 @@ async def test_method_list(self, async_client: AsyncIncrease) -> None: @parametrize async def test_method_list_with_all_params(self, async_client: AsyncIncrease) -> None: export = await async_client.exports.list( - category={"in": ["account_statement_ofx"]}, + category="account_statement_ofx", created_at={ "after": parse_datetime("2019-12-27T18:11:19.117Z"), "before": parse_datetime("2019-12-27T18:11:19.117Z"), @@ -335,6 +341,8 @@ async def test_method_list_with_all_params(self, async_client: AsyncIncrease) -> "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), }, cursor="cursor", + form_1099_int={"account_id": "account_id"}, + form_1099_misc={"account_id": "account_id"}, idempotency_key="x", limit=1, status={"in": ["pending"]}, diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index e36671d6d..172094476 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -22,7 +22,7 @@ class TestFiles: @parametrize def test_method_create(self, client: Increase) -> None: file = client.files.create( - file=b"raw file contents", + file=b"Example data", purpose="check_image_front", ) assert_matches_type(File, file, path=["response"]) @@ -30,7 +30,7 @@ def test_method_create(self, client: Increase) -> None: @parametrize def test_method_create_with_all_params(self, client: Increase) -> None: file = client.files.create( - file=b"raw file contents", + file=b"Example data", purpose="check_image_front", description="x", ) @@ -39,7 +39,7 @@ def test_method_create_with_all_params(self, client: Increase) -> None: @parametrize def test_raw_response_create(self, client: Increase) -> None: response = client.files.with_raw_response.create( - file=b"raw file contents", + file=b"Example data", purpose="check_image_front", ) @@ -51,7 +51,7 @@ def test_raw_response_create(self, client: Increase) -> None: @parametrize def test_streaming_response_create(self, client: Increase) -> None: with client.files.with_streaming_response.create( - file=b"raw file contents", + file=b"Example data", purpose="check_image_front", ) as response: assert not response.is_closed @@ -150,7 +150,7 @@ class TestAsyncFiles: @parametrize async def test_method_create(self, async_client: AsyncIncrease) -> None: file = await async_client.files.create( - file=b"raw file contents", + file=b"Example data", purpose="check_image_front", ) assert_matches_type(File, file, path=["response"]) @@ -158,7 +158,7 @@ async def test_method_create(self, async_client: AsyncIncrease) -> None: @parametrize async def test_method_create_with_all_params(self, async_client: AsyncIncrease) -> None: file = await async_client.files.create( - file=b"raw file contents", + file=b"Example data", purpose="check_image_front", description="x", ) @@ -167,7 +167,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncIncrease) @parametrize async def test_raw_response_create(self, async_client: AsyncIncrease) -> None: response = await async_client.files.with_raw_response.create( - file=b"raw file contents", + file=b"Example data", purpose="check_image_front", ) @@ -179,7 +179,7 @@ async def test_raw_response_create(self, async_client: AsyncIncrease) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncIncrease) -> None: async with async_client.files.with_streaming_response.create( - file=b"raw file contents", + file=b"Example data", purpose="check_image_front", ) as response: assert not response.is_closed diff --git a/tests/api_resources/test_intrafi_exclusions.py b/tests/api_resources/test_intrafi_exclusions.py index b3564fc62..ba9928995 100644 --- a/tests/api_resources/test_intrafi_exclusions.py +++ b/tests/api_resources/test_intrafi_exclusions.py @@ -21,16 +21,16 @@ class TestIntrafiExclusions: @parametrize def test_method_create(self, client: Increase) -> None: intrafi_exclusion = client.intrafi_exclusions.create( - bank_name="Example Bank", entity_id="entity_n8y8tnk2p9339ti393yi", + fdic_certificate_number="314159", ) assert_matches_type(IntrafiExclusion, intrafi_exclusion, path=["response"]) @parametrize def test_raw_response_create(self, client: Increase) -> None: response = client.intrafi_exclusions.with_raw_response.create( - bank_name="Example Bank", entity_id="entity_n8y8tnk2p9339ti393yi", + fdic_certificate_number="314159", ) assert response.is_closed is True @@ -41,8 +41,8 @@ def test_raw_response_create(self, client: Increase) -> None: @parametrize def test_streaming_response_create(self, client: Increase) -> None: with client.intrafi_exclusions.with_streaming_response.create( - bank_name="Example Bank", entity_id="entity_n8y8tnk2p9339ti393yi", + fdic_certificate_number="314159", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -172,16 +172,16 @@ class TestAsyncIntrafiExclusions: @parametrize async def test_method_create(self, async_client: AsyncIncrease) -> None: intrafi_exclusion = await async_client.intrafi_exclusions.create( - bank_name="Example Bank", entity_id="entity_n8y8tnk2p9339ti393yi", + fdic_certificate_number="314159", ) assert_matches_type(IntrafiExclusion, intrafi_exclusion, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncIncrease) -> None: response = await async_client.intrafi_exclusions.with_raw_response.create( - bank_name="Example Bank", entity_id="entity_n8y8tnk2p9339ti393yi", + fdic_certificate_number="314159", ) assert response.is_closed is True @@ -192,8 +192,8 @@ async def test_raw_response_create(self, async_client: AsyncIncrease) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncIncrease) -> None: async with async_client.intrafi_exclusions.with_streaming_response.create( - bank_name="Example Bank", entity_id="entity_n8y8tnk2p9339ti393yi", + fdic_certificate_number="314159", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/test_real_time_decisions.py b/tests/api_resources/test_real_time_decisions.py index 57855613a..c25362743 100644 --- a/tests/api_resources/test_real_time_decisions.py +++ b/tests/api_resources/test_real_time_decisions.py @@ -67,7 +67,13 @@ def test_method_action_with_all_params(self, client: Increase) -> None: real_time_decision = client.real_time_decisions.action( real_time_decision_id="real_time_decision_j76n2e810ezcg3zh5qtn", card_authentication={"decision": "approve"}, - card_authentication_challenge={"result": "success"}, + card_authentication_challenge={ + "result": "success", + "success": { + "email": "dev@stainless.com", + "phone": "x", + }, + }, card_authorization={ "decision": "approve", "approval": { @@ -187,7 +193,13 @@ async def test_method_action_with_all_params(self, async_client: AsyncIncrease) real_time_decision = await async_client.real_time_decisions.action( real_time_decision_id="real_time_decision_j76n2e810ezcg3zh5qtn", card_authentication={"decision": "approve"}, - card_authentication_challenge={"result": "success"}, + card_authentication_challenge={ + "result": "success", + "success": { + "email": "dev@stainless.com", + "phone": "x", + }, + }, card_authorization={ "decision": "approve", "approval": { diff --git a/tests/api_resources/test_swift_transfers.py b/tests/api_resources/test_swift_transfers.py new file mode 100644 index 000000000..f2e2a35df --- /dev/null +++ b/tests/api_resources/test_swift_transfers.py @@ -0,0 +1,574 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from increase import Increase, AsyncIncrease +from tests.utils import assert_matches_type +from increase.types import SwiftTransfer +from increase._utils import parse_datetime +from increase.pagination import SyncPage, AsyncPage + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestSwiftTransfers: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Increase) -> None: + swift_transfer = client.swift_transfers.create( + account_id="account_in71c4amph0vgo2qllky", + account_number="987654321", + bank_identification_code="ECBFDEFFTPP", + creditor_address={ + "city": "Frankfurt", + "country": "DE", + "line1": "Sonnemannstrasse 20", + }, + creditor_name="Ian Crease", + debtor_address={ + "city": "New York", + "country": "US", + "line1": "33 Liberty Street", + }, + debtor_name="National Phonograph Company", + instructed_amount=100, + instructed_currency="USD", + source_account_number_id="account_number_v18nkfqm6afpsrvy82b2", + unstructured_remittance_information="New Swift transfer", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Increase) -> None: + swift_transfer = client.swift_transfers.create( + account_id="account_in71c4amph0vgo2qllky", + account_number="987654321", + bank_identification_code="ECBFDEFFTPP", + creditor_address={ + "city": "Frankfurt", + "country": "DE", + "line1": "Sonnemannstrasse 20", + "line2": "x", + "postal_code": "60314", + "state": "x", + }, + creditor_name="Ian Crease", + debtor_address={ + "city": "New York", + "country": "US", + "line1": "33 Liberty Street", + "line2": "x", + "postal_code": "10045", + "state": "NY", + }, + debtor_name="National Phonograph Company", + instructed_amount=100, + instructed_currency="USD", + source_account_number_id="account_number_v18nkfqm6afpsrvy82b2", + unstructured_remittance_information="New Swift transfer", + require_approval=True, + routing_number="x", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Increase) -> None: + response = client.swift_transfers.with_raw_response.create( + account_id="account_in71c4amph0vgo2qllky", + account_number="987654321", + bank_identification_code="ECBFDEFFTPP", + creditor_address={ + "city": "Frankfurt", + "country": "DE", + "line1": "Sonnemannstrasse 20", + }, + creditor_name="Ian Crease", + debtor_address={ + "city": "New York", + "country": "US", + "line1": "33 Liberty Street", + }, + debtor_name="National Phonograph Company", + instructed_amount=100, + instructed_currency="USD", + source_account_number_id="account_number_v18nkfqm6afpsrvy82b2", + unstructured_remittance_information="New Swift transfer", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Increase) -> None: + with client.swift_transfers.with_streaming_response.create( + account_id="account_in71c4amph0vgo2qllky", + account_number="987654321", + bank_identification_code="ECBFDEFFTPP", + creditor_address={ + "city": "Frankfurt", + "country": "DE", + "line1": "Sonnemannstrasse 20", + }, + creditor_name="Ian Crease", + debtor_address={ + "city": "New York", + "country": "US", + "line1": "33 Liberty Street", + }, + debtor_name="National Phonograph Company", + instructed_amount=100, + instructed_currency="USD", + source_account_number_id="account_number_v18nkfqm6afpsrvy82b2", + unstructured_remittance_information="New Swift transfer", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_retrieve(self, client: Increase) -> None: + swift_transfer = client.swift_transfers.retrieve( + "swift_transfer_29h21xkng03788zwd3fh", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Increase) -> None: + response = client.swift_transfers.with_raw_response.retrieve( + "swift_transfer_29h21xkng03788zwd3fh", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Increase) -> None: + with client.swift_transfers.with_streaming_response.retrieve( + "swift_transfer_29h21xkng03788zwd3fh", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: Increase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `swift_transfer_id` but received ''"): + client.swift_transfers.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_list(self, client: Increase) -> None: + swift_transfer = client.swift_transfers.list() + assert_matches_type(SyncPage[SwiftTransfer], swift_transfer, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Increase) -> None: + swift_transfer = client.swift_transfers.list( + account_id="account_id", + created_at={ + "after": parse_datetime("2019-12-27T18:11:19.117Z"), + "before": parse_datetime("2019-12-27T18:11:19.117Z"), + "on_or_after": parse_datetime("2019-12-27T18:11:19.117Z"), + "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), + }, + cursor="cursor", + idempotency_key="x", + limit=1, + status={"in": ["pending_approval"]}, + ) + assert_matches_type(SyncPage[SwiftTransfer], swift_transfer, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Increase) -> None: + response = client.swift_transfers.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = response.parse() + assert_matches_type(SyncPage[SwiftTransfer], swift_transfer, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Increase) -> None: + with client.swift_transfers.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = response.parse() + assert_matches_type(SyncPage[SwiftTransfer], swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_approve(self, client: Increase) -> None: + swift_transfer = client.swift_transfers.approve( + "swift_transfer_29h21xkng03788zwd3fh", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_raw_response_approve(self, client: Increase) -> None: + response = client.swift_transfers.with_raw_response.approve( + "swift_transfer_29h21xkng03788zwd3fh", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_streaming_response_approve(self, client: Increase) -> None: + with client.swift_transfers.with_streaming_response.approve( + "swift_transfer_29h21xkng03788zwd3fh", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_approve(self, client: Increase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `swift_transfer_id` but received ''"): + client.swift_transfers.with_raw_response.approve( + "", + ) + + @parametrize + def test_method_cancel(self, client: Increase) -> None: + swift_transfer = client.swift_transfers.cancel( + "swift_transfer_29h21xkng03788zwd3fh", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_raw_response_cancel(self, client: Increase) -> None: + response = client.swift_transfers.with_raw_response.cancel( + "swift_transfer_29h21xkng03788zwd3fh", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + def test_streaming_response_cancel(self, client: Increase) -> None: + with client.swift_transfers.with_streaming_response.cancel( + "swift_transfer_29h21xkng03788zwd3fh", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_cancel(self, client: Increase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `swift_transfer_id` but received ''"): + client.swift_transfers.with_raw_response.cancel( + "", + ) + + +class TestAsyncSwiftTransfers: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncIncrease) -> None: + swift_transfer = await async_client.swift_transfers.create( + account_id="account_in71c4amph0vgo2qllky", + account_number="987654321", + bank_identification_code="ECBFDEFFTPP", + creditor_address={ + "city": "Frankfurt", + "country": "DE", + "line1": "Sonnemannstrasse 20", + }, + creditor_name="Ian Crease", + debtor_address={ + "city": "New York", + "country": "US", + "line1": "33 Liberty Street", + }, + debtor_name="National Phonograph Company", + instructed_amount=100, + instructed_currency="USD", + source_account_number_id="account_number_v18nkfqm6afpsrvy82b2", + unstructured_remittance_information="New Swift transfer", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncIncrease) -> None: + swift_transfer = await async_client.swift_transfers.create( + account_id="account_in71c4amph0vgo2qllky", + account_number="987654321", + bank_identification_code="ECBFDEFFTPP", + creditor_address={ + "city": "Frankfurt", + "country": "DE", + "line1": "Sonnemannstrasse 20", + "line2": "x", + "postal_code": "60314", + "state": "x", + }, + creditor_name="Ian Crease", + debtor_address={ + "city": "New York", + "country": "US", + "line1": "33 Liberty Street", + "line2": "x", + "postal_code": "10045", + "state": "NY", + }, + debtor_name="National Phonograph Company", + instructed_amount=100, + instructed_currency="USD", + source_account_number_id="account_number_v18nkfqm6afpsrvy82b2", + unstructured_remittance_information="New Swift transfer", + require_approval=True, + routing_number="x", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncIncrease) -> None: + response = await async_client.swift_transfers.with_raw_response.create( + account_id="account_in71c4amph0vgo2qllky", + account_number="987654321", + bank_identification_code="ECBFDEFFTPP", + creditor_address={ + "city": "Frankfurt", + "country": "DE", + "line1": "Sonnemannstrasse 20", + }, + creditor_name="Ian Crease", + debtor_address={ + "city": "New York", + "country": "US", + "line1": "33 Liberty Street", + }, + debtor_name="National Phonograph Company", + instructed_amount=100, + instructed_currency="USD", + source_account_number_id="account_number_v18nkfqm6afpsrvy82b2", + unstructured_remittance_information="New Swift transfer", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = await response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncIncrease) -> None: + async with async_client.swift_transfers.with_streaming_response.create( + account_id="account_in71c4amph0vgo2qllky", + account_number="987654321", + bank_identification_code="ECBFDEFFTPP", + creditor_address={ + "city": "Frankfurt", + "country": "DE", + "line1": "Sonnemannstrasse 20", + }, + creditor_name="Ian Crease", + debtor_address={ + "city": "New York", + "country": "US", + "line1": "33 Liberty Street", + }, + debtor_name="National Phonograph Company", + instructed_amount=100, + instructed_currency="USD", + source_account_number_id="account_number_v18nkfqm6afpsrvy82b2", + unstructured_remittance_information="New Swift transfer", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = await response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_retrieve(self, async_client: AsyncIncrease) -> None: + swift_transfer = await async_client.swift_transfers.retrieve( + "swift_transfer_29h21xkng03788zwd3fh", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncIncrease) -> None: + response = await async_client.swift_transfers.with_raw_response.retrieve( + "swift_transfer_29h21xkng03788zwd3fh", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = await response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncIncrease) -> None: + async with async_client.swift_transfers.with_streaming_response.retrieve( + "swift_transfer_29h21xkng03788zwd3fh", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = await response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncIncrease) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `swift_transfer_id` but received ''"): + await async_client.swift_transfers.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncIncrease) -> None: + swift_transfer = await async_client.swift_transfers.list() + assert_matches_type(AsyncPage[SwiftTransfer], swift_transfer, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncIncrease) -> None: + swift_transfer = await async_client.swift_transfers.list( + account_id="account_id", + created_at={ + "after": parse_datetime("2019-12-27T18:11:19.117Z"), + "before": parse_datetime("2019-12-27T18:11:19.117Z"), + "on_or_after": parse_datetime("2019-12-27T18:11:19.117Z"), + "on_or_before": parse_datetime("2019-12-27T18:11:19.117Z"), + }, + cursor="cursor", + idempotency_key="x", + limit=1, + status={"in": ["pending_approval"]}, + ) + assert_matches_type(AsyncPage[SwiftTransfer], swift_transfer, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncIncrease) -> None: + response = await async_client.swift_transfers.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = await response.parse() + assert_matches_type(AsyncPage[SwiftTransfer], swift_transfer, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncIncrease) -> None: + async with async_client.swift_transfers.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = await response.parse() + assert_matches_type(AsyncPage[SwiftTransfer], swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_approve(self, async_client: AsyncIncrease) -> None: + swift_transfer = await async_client.swift_transfers.approve( + "swift_transfer_29h21xkng03788zwd3fh", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_raw_response_approve(self, async_client: AsyncIncrease) -> None: + response = await async_client.swift_transfers.with_raw_response.approve( + "swift_transfer_29h21xkng03788zwd3fh", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = await response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_streaming_response_approve(self, async_client: AsyncIncrease) -> None: + async with async_client.swift_transfers.with_streaming_response.approve( + "swift_transfer_29h21xkng03788zwd3fh", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = await response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_approve(self, async_client: AsyncIncrease) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `swift_transfer_id` but received ''"): + await async_client.swift_transfers.with_raw_response.approve( + "", + ) + + @parametrize + async def test_method_cancel(self, async_client: AsyncIncrease) -> None: + swift_transfer = await async_client.swift_transfers.cancel( + "swift_transfer_29h21xkng03788zwd3fh", + ) + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_raw_response_cancel(self, async_client: AsyncIncrease) -> None: + response = await async_client.swift_transfers.with_raw_response.cancel( + "swift_transfer_29h21xkng03788zwd3fh", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + swift_transfer = await response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + @parametrize + async def test_streaming_response_cancel(self, async_client: AsyncIncrease) -> None: + async with async_client.swift_transfers.with_streaming_response.cancel( + "swift_transfer_29h21xkng03788zwd3fh", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + swift_transfer = await response.parse() + assert_matches_type(SwiftTransfer, swift_transfer, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_cancel(self, async_client: AsyncIncrease) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `swift_transfer_id` but received ''"): + await async_client.swift_transfers.with_raw_response.cancel( + "", + ) diff --git a/tests/api_resources/test_wire_drawdown_requests.py b/tests/api_resources/test_wire_drawdown_requests.py index dd4783e33..826ff461a 100644 --- a/tests/api_resources/test_wire_drawdown_requests.py +++ b/tests/api_resources/test_wire_drawdown_requests.py @@ -66,6 +66,7 @@ def test_method_create_with_all_params(self, client: Increase) -> None: debtor_account_number="987654321", debtor_external_account_id="debtor_external_account_id", debtor_routing_number="101050001", + end_to_end_identification="x", ) assert_matches_type(WireDrawdownRequest, wire_drawdown_request, path=["response"]) @@ -250,6 +251,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncIncrease) debtor_account_number="987654321", debtor_external_account_id="debtor_external_account_id", debtor_routing_number="101050001", + end_to_end_identification="x", ) assert_matches_type(WireDrawdownRequest, wire_drawdown_request, path=["response"]) diff --git a/tests/api_resources/test_wire_transfers.py b/tests/api_resources/test_wire_transfers.py index e68b36452..77b147967 100644 --- a/tests/api_resources/test_wire_transfers.py +++ b/tests/api_resources/test_wire_transfers.py @@ -159,6 +159,7 @@ def test_method_list_with_all_params(self, client: Increase) -> None: external_account_id="external_account_id", idempotency_key="x", limit=1, + status={"in": ["pending_approval"]}, ) assert_matches_type(SyncPage[WireTransfer], wire_transfer, path=["response"]) @@ -404,6 +405,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncIncrease) -> external_account_id="external_account_id", idempotency_key="x", limit=1, + status={"in": ["pending_approval"]}, ) assert_matches_type(AsyncPage[WireTransfer], wire_transfer, path=["response"]) diff --git a/tests/test_client.py b/tests/test_client.py index 3122d2f29..c0e8cde5e 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -8,10 +8,11 @@ import json import asyncio import inspect +import dataclasses import tracemalloc -from typing import Any, Union, cast +from typing import Any, Union, TypeVar, Callable, Iterable, Iterator, Optional, Coroutine, cast from unittest import mock -from typing_extensions import Literal +from typing_extensions import Literal, AsyncIterator, override import httpx import pytest @@ -36,6 +37,7 @@ from .utils import update_env +T = TypeVar("T") base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") api_key = "My API Key" @@ -50,6 +52,57 @@ def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: return 0.1 +def mirror_request_content(request: httpx.Request) -> httpx.Response: + return httpx.Response(200, content=request.content) + + +# note: we can't use the httpx.MockTransport class as it consumes the request +# body itself, which means we can't test that the body is read lazily +class MockTransport(httpx.BaseTransport, httpx.AsyncBaseTransport): + def __init__( + self, + handler: Callable[[httpx.Request], httpx.Response] + | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], + ) -> None: + self.handler = handler + + @override + def handle_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" + assert inspect.isfunction(self.handler), "handler must be a function" + return self.handler(request) + + @override + async def handle_async_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" + return await self.handler(request) + + +@dataclasses.dataclass +class Counter: + value: int = 0 + + +def _make_sync_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> Iterator[T]: + for item in iterable: + if counter: + counter.value += 1 + yield item + + +async def _make_async_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> AsyncIterator[T]: + for item in iterable: + if counter: + counter.value += 1 + yield item + + def _get_open_connections(client: Increase | AsyncIncrease) -> int: transport = client._client._transport assert isinstance(transport, httpx.HTTPTransport) or isinstance(transport, httpx.AsyncHTTPTransport) @@ -502,6 +555,70 @@ def test_multipart_repeating_array(self, client: Increase) -> None: b"", ] + @pytest.mark.respx(base_url=base_url) + def test_binary_content_upload(self, respx_mock: MockRouter, client: Increase) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + response = client.post( + "/upload", + content=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + + def test_binary_content_upload_with_iterator(self) -> None: + file_content = b"Hello, this is a test file." + counter = Counter() + iterator = _make_sync_iterator([file_content], counter=counter) + + def mock_handler(request: httpx.Request) -> httpx.Response: + assert counter.value == 0, "the request body should not have been read" + return httpx.Response(200, content=request.read()) + + with Increase( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.Client(transport=MockTransport(handler=mock_handler)), + ) as client: + response = client.post( + "/upload", + content=iterator, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 + + @pytest.mark.respx(base_url=base_url) + def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, client: Increase) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + with pytest.deprecated_call( + match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." + ): + response = client.post( + "/upload", + body=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + @pytest.mark.respx(base_url=base_url) def test_basic_union_response(self, respx_mock: MockRouter, client: Increase) -> None: class Model1(BaseModel): @@ -877,6 +994,14 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly monkeypatch.setenv("HTTPS_PROXY", "https://example.org") + # Delete in case our environment has any proxy env vars set + monkeypatch.delenv("HTTP_PROXY", raising=False) + monkeypatch.delenv("ALL_PROXY", raising=False) + monkeypatch.delenv("NO_PROXY", raising=False) + monkeypatch.delenv("http_proxy", raising=False) + monkeypatch.delenv("https_proxy", raising=False) + monkeypatch.delenv("all_proxy", raising=False) + monkeypatch.delenv("no_proxy", raising=False) client = DefaultHttpxClient() @@ -1368,6 +1493,72 @@ def test_multipart_repeating_array(self, async_client: AsyncIncrease) -> None: b"", ] + @pytest.mark.respx(base_url=base_url) + async def test_binary_content_upload(self, respx_mock: MockRouter, async_client: AsyncIncrease) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + response = await async_client.post( + "/upload", + content=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + + async def test_binary_content_upload_with_asynciterator(self) -> None: + file_content = b"Hello, this is a test file." + counter = Counter() + iterator = _make_async_iterator([file_content], counter=counter) + + async def mock_handler(request: httpx.Request) -> httpx.Response: + assert counter.value == 0, "the request body should not have been read" + return httpx.Response(200, content=await request.aread()) + + async with AsyncIncrease( + base_url=base_url, + api_key=api_key, + _strict_response_validation=True, + http_client=httpx.AsyncClient(transport=MockTransport(handler=mock_handler)), + ) as client: + response = await client.post( + "/upload", + content=iterator, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 + + @pytest.mark.respx(base_url=base_url) + async def test_binary_content_upload_with_body_is_deprecated( + self, respx_mock: MockRouter, async_client: AsyncIncrease + ) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + with pytest.deprecated_call( + match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." + ): + response = await async_client.post( + "/upload", + body=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + @pytest.mark.respx(base_url=base_url) async def test_basic_union_response(self, respx_mock: MockRouter, async_client: AsyncIncrease) -> None: class Model1(BaseModel): @@ -1764,6 +1955,14 @@ async def test_get_platform(self) -> None: async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly monkeypatch.setenv("HTTPS_PROXY", "https://example.org") + # Delete in case our environment has any proxy env vars set + monkeypatch.delenv("HTTP_PROXY", raising=False) + monkeypatch.delenv("ALL_PROXY", raising=False) + monkeypatch.delenv("NO_PROXY", raising=False) + monkeypatch.delenv("http_proxy", raising=False) + monkeypatch.delenv("https_proxy", raising=False) + monkeypatch.delenv("all_proxy", raising=False) + monkeypatch.delenv("no_proxy", raising=False) client = DefaultAsyncHttpxClient() diff --git a/tests/test_utils/test_json.py b/tests/test_utils/test_json.py new file mode 100644 index 000000000..30acb42bc --- /dev/null +++ b/tests/test_utils/test_json.py @@ -0,0 +1,126 @@ +from __future__ import annotations + +import datetime +from typing import Union + +import pydantic + +from increase import _compat +from increase._utils._json import openapi_dumps + + +class TestOpenapiDumps: + def test_basic(self) -> None: + data = {"key": "value", "number": 42} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"key":"value","number":42}' + + def test_datetime_serialization(self) -> None: + dt = datetime.datetime(2023, 1, 1, 12, 0, 0) + data = {"datetime": dt} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"datetime":"2023-01-01T12:00:00"}' + + def test_pydantic_model_serialization(self) -> None: + class User(pydantic.BaseModel): + first_name: str + last_name: str + age: int + + model_instance = User(first_name="John", last_name="Kramer", age=83) + data = {"model": model_instance} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"model":{"first_name":"John","last_name":"Kramer","age":83}}' + + def test_pydantic_model_with_default_values(self) -> None: + class User(pydantic.BaseModel): + name: str + role: str = "user" + active: bool = True + score: int = 0 + + model_instance = User(name="Alice") + data = {"model": model_instance} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"model":{"name":"Alice"}}' + + def test_pydantic_model_with_default_values_overridden(self) -> None: + class User(pydantic.BaseModel): + name: str + role: str = "user" + active: bool = True + + model_instance = User(name="Bob", role="admin", active=False) + data = {"model": model_instance} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"model":{"name":"Bob","role":"admin","active":false}}' + + def test_pydantic_model_with_alias(self) -> None: + class User(pydantic.BaseModel): + first_name: str = pydantic.Field(alias="firstName") + last_name: str = pydantic.Field(alias="lastName") + + model_instance = User(firstName="John", lastName="Doe") + data = {"model": model_instance} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"model":{"firstName":"John","lastName":"Doe"}}' + + def test_pydantic_model_with_alias_and_default(self) -> None: + class User(pydantic.BaseModel): + user_name: str = pydantic.Field(alias="userName") + user_role: str = pydantic.Field(default="member", alias="userRole") + is_active: bool = pydantic.Field(default=True, alias="isActive") + + model_instance = User(userName="charlie") + data = {"model": model_instance} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"model":{"userName":"charlie"}}' + + model_with_overrides = User(userName="diana", userRole="admin", isActive=False) + data = {"model": model_with_overrides} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"model":{"userName":"diana","userRole":"admin","isActive":false}}' + + def test_pydantic_model_with_nested_models_and_defaults(self) -> None: + class Address(pydantic.BaseModel): + street: str + city: str = "Unknown" + + class User(pydantic.BaseModel): + name: str + address: Address + verified: bool = False + + if _compat.PYDANTIC_V1: + # to handle forward references in Pydantic v1 + User.update_forward_refs(**locals()) # type: ignore[reportDeprecated] + + address = Address(street="123 Main St") + user = User(name="Diana", address=address) + data = {"user": user} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"user":{"name":"Diana","address":{"street":"123 Main St"}}}' + + address_with_city = Address(street="456 Oak Ave", city="Boston") + user_verified = User(name="Eve", address=address_with_city, verified=True) + data = {"user": user_verified} + json_bytes = openapi_dumps(data) + assert ( + json_bytes == b'{"user":{"name":"Eve","address":{"street":"456 Oak Ave","city":"Boston"},"verified":true}}' + ) + + def test_pydantic_model_with_optional_fields(self) -> None: + class User(pydantic.BaseModel): + name: str + email: Union[str, None] + phone: Union[str, None] + + model_with_none = User(name="Eve", email=None, phone=None) + data = {"model": model_with_none} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"model":{"name":"Eve","email":null,"phone":null}}' + + model_with_values = User(name="Frank", email="frank@example.com", phone=None) + data = {"model": model_with_values} + json_bytes = openapi_dumps(data) + assert json_bytes == b'{"model":{"name":"Frank","email":"frank@example.com","phone":null}}'